Class: PGN::Position

Inherits:
Object
  • Object
show all
Defined in:
lib/pgn/position.rb

Overview

Position encapsulates all of the information necessary to completely understand a chess position. It can be turned into a FEN string or perform a move.

Constant Summary collapse

PLAYERS =
[:white, :black]
CASTLING =
%w{K Q k q}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(board, player, castling = CASTLING, en_passant = nil, halfmove = 0, fullmove = 1) ⇒ Position

Returns a new instance of Position.

Examples:

PGN::Position.new(
  PGN::Board.start,
  :white,
)


64
65
66
67
68
69
70
71
# File 'lib/pgn/position.rb', line 64

def initialize(board, player, castling = CASTLING, en_passant = nil, halfmove = 0, fullmove = 1)
  self.board      = board
  self.player     = player
  self.castling   = castling
  self.en_passant = en_passant
  self.halfmove   = halfmove
  self.fullmove   = fullmove
end

Instance Attribute Details

#boardPGN::Board



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
121
122
123
124
# File 'lib/pgn/position.rb', line 29

class Position
  PLAYERS  = [:white, :black]
  CASTLING = %w{K Q k q}

  attr_accessor :board
  attr_accessor :player
  attr_accessor :castling
  attr_accessor :en_passant
  attr_accessor :halfmove
  attr_accessor :fullmove

  # @return [PGN::Position] the starting position of a chess game
  #
  def self.start
    PGN::Position.new(
      PGN::Board.start,
      PLAYERS.first,
    )
  end

  # @param board [PGN::Board] the board for the position
  # @param player [Symbol] the player who moves next
  # @param castling [Array<String>] the castling moves that are still
  #   available
  # @param en_passant [String, nil] the en passant square if applicable
  # @param halfmove [Integer] the number of halfmoves since the last pawn
  #   move or capture
  # @param fullmove [Integer] the number of fullmoves made so far
  #
  # @example
  #   PGN::Position.new(
  #     PGN::Board.start,
  #     :white,
  #   )
  #
  def initialize(board, player, castling = CASTLING, en_passant = nil, halfmove = 0, fullmove = 1)
    self.board      = board
    self.player     = player
    self.castling   = castling
    self.en_passant = en_passant
    self.halfmove   = halfmove
    self.fullmove   = fullmove
  end 

  # @param str [String] the move to make in SAN
  # @return [PGN::Position] the resulting position
  #
  # @example
  #   queens_pawn = PGN::Position.start.move("d4")
  #
  def move(str)
    move       = PGN::Move.new(str, self.player)
    calculator = PGN::MoveCalculator.new(self.board, move)

    new_castling = self.castling - calculator.castling_restrictions
    new_halfmove = calculator.increment_halfmove? ?
      self.halfmove + 1 :
      0
    new_fullmove = calculator.increment_fullmove? ?
      self.fullmove + 1 :
      self.fullmove

    PGN::Position.new(
      calculator.result_board,
      self.next_player,
      new_castling,
      calculator.en_passant_square,
      new_halfmove,
      new_fullmove,
    )
  end

  # @return [Symbol] the next player to move
  #
  def next_player
    (PLAYERS - [self.player]).first
  end

  def inspect
    "\n" + self.board.inspect
  end

  # @return [PGN::FEN] a {PGN::FEN} object representing the current position
  #
  def to_fen
    PGN::FEN.from_attributes(
      board:      self.board,
      active:     self.player == :white ? 'w' : 'b',
      castling:   self.castling.join(''),
      en_passant: self.en_passant,
      halfmove:   self.halfmove.to_s,
      fullmove:   self.fullmove.to_s,
    )
  end

end

#castlingArray<String>

Returns the castling moves that are still available.

Examples:

position.castling #=> ["K", "k", "q"]


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
121
122
123
124
# File 'lib/pgn/position.rb', line 29

class Position
  PLAYERS  = [:white, :black]
  CASTLING = %w{K Q k q}

  attr_accessor :board
  attr_accessor :player
  attr_accessor :castling
  attr_accessor :en_passant
  attr_accessor :halfmove
  attr_accessor :fullmove

  # @return [PGN::Position] the starting position of a chess game
  #
  def self.start
    PGN::Position.new(
      PGN::Board.start,
      PLAYERS.first,
    )
  end

  # @param board [PGN::Board] the board for the position
  # @param player [Symbol] the player who moves next
  # @param castling [Array<String>] the castling moves that are still
  #   available
  # @param en_passant [String, nil] the en passant square if applicable
  # @param halfmove [Integer] the number of halfmoves since the last pawn
  #   move or capture
  # @param fullmove [Integer] the number of fullmoves made so far
  #
  # @example
  #   PGN::Position.new(
  #     PGN::Board.start,
  #     :white,
  #   )
  #
  def initialize(board, player, castling = CASTLING, en_passant = nil, halfmove = 0, fullmove = 1)
    self.board      = board
    self.player     = player
    self.castling   = castling
    self.en_passant = en_passant
    self.halfmove   = halfmove
    self.fullmove   = fullmove
  end 

  # @param str [String] the move to make in SAN
  # @return [PGN::Position] the resulting position
  #
  # @example
  #   queens_pawn = PGN::Position.start.move("d4")
  #
  def move(str)
    move       = PGN::Move.new(str, self.player)
    calculator = PGN::MoveCalculator.new(self.board, move)

    new_castling = self.castling - calculator.castling_restrictions
    new_halfmove = calculator.increment_halfmove? ?
      self.halfmove + 1 :
      0
    new_fullmove = calculator.increment_fullmove? ?
      self.fullmove + 1 :
      self.fullmove

    PGN::Position.new(
      calculator.result_board,
      self.next_player,
      new_castling,
      calculator.en_passant_square,
      new_halfmove,
      new_fullmove,
    )
  end

  # @return [Symbol] the next player to move
  #
  def next_player
    (PLAYERS - [self.player]).first
  end

  def inspect
    "\n" + self.board.inspect
  end

  # @return [PGN::FEN] a {PGN::FEN} object representing the current position
  #
  def to_fen
    PGN::FEN.from_attributes(
      board:      self.board,
      active:     self.player == :white ? 'w' : 'b',
      castling:   self.castling.join(''),
      en_passant: self.en_passant,
      halfmove:   self.halfmove.to_s,
      fullmove:   self.fullmove.to_s,
    )
  end

end

#en_passantString



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
121
122
123
124
# File 'lib/pgn/position.rb', line 29

class Position
  PLAYERS  = [:white, :black]
  CASTLING = %w{K Q k q}

  attr_accessor :board
  attr_accessor :player
  attr_accessor :castling
  attr_accessor :en_passant
  attr_accessor :halfmove
  attr_accessor :fullmove

  # @return [PGN::Position] the starting position of a chess game
  #
  def self.start
    PGN::Position.new(
      PGN::Board.start,
      PLAYERS.first,
    )
  end

  # @param board [PGN::Board] the board for the position
  # @param player [Symbol] the player who moves next
  # @param castling [Array<String>] the castling moves that are still
  #   available
  # @param en_passant [String, nil] the en passant square if applicable
  # @param halfmove [Integer] the number of halfmoves since the last pawn
  #   move or capture
  # @param fullmove [Integer] the number of fullmoves made so far
  #
  # @example
  #   PGN::Position.new(
  #     PGN::Board.start,
  #     :white,
  #   )
  #
  def initialize(board, player, castling = CASTLING, en_passant = nil, halfmove = 0, fullmove = 1)
    self.board      = board
    self.player     = player
    self.castling   = castling
    self.en_passant = en_passant
    self.halfmove   = halfmove
    self.fullmove   = fullmove
  end 

  # @param str [String] the move to make in SAN
  # @return [PGN::Position] the resulting position
  #
  # @example
  #   queens_pawn = PGN::Position.start.move("d4")
  #
  def move(str)
    move       = PGN::Move.new(str, self.player)
    calculator = PGN::MoveCalculator.new(self.board, move)

    new_castling = self.castling - calculator.castling_restrictions
    new_halfmove = calculator.increment_halfmove? ?
      self.halfmove + 1 :
      0
    new_fullmove = calculator.increment_fullmove? ?
      self.fullmove + 1 :
      self.fullmove

    PGN::Position.new(
      calculator.result_board,
      self.next_player,
      new_castling,
      calculator.en_passant_square,
      new_halfmove,
      new_fullmove,
    )
  end

  # @return [Symbol] the next player to move
  #
  def next_player
    (PLAYERS - [self.player]).first
  end

  def inspect
    "\n" + self.board.inspect
  end

  # @return [PGN::FEN] a {PGN::FEN} object representing the current position
  #
  def to_fen
    PGN::FEN.from_attributes(
      board:      self.board,
      active:     self.player == :white ? 'w' : 'b',
      castling:   self.castling.join(''),
      en_passant: self.en_passant,
      halfmove:   self.halfmove.to_s,
      fullmove:   self.fullmove.to_s,
    )
  end

end

#fullmoveInteger



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
121
122
123
124
# File 'lib/pgn/position.rb', line 29

class Position
  PLAYERS  = [:white, :black]
  CASTLING = %w{K Q k q}

  attr_accessor :board
  attr_accessor :player
  attr_accessor :castling
  attr_accessor :en_passant
  attr_accessor :halfmove
  attr_accessor :fullmove

  # @return [PGN::Position] the starting position of a chess game
  #
  def self.start
    PGN::Position.new(
      PGN::Board.start,
      PLAYERS.first,
    )
  end

  # @param board [PGN::Board] the board for the position
  # @param player [Symbol] the player who moves next
  # @param castling [Array<String>] the castling moves that are still
  #   available
  # @param en_passant [String, nil] the en passant square if applicable
  # @param halfmove [Integer] the number of halfmoves since the last pawn
  #   move or capture
  # @param fullmove [Integer] the number of fullmoves made so far
  #
  # @example
  #   PGN::Position.new(
  #     PGN::Board.start,
  #     :white,
  #   )
  #
  def initialize(board, player, castling = CASTLING, en_passant = nil, halfmove = 0, fullmove = 1)
    self.board      = board
    self.player     = player
    self.castling   = castling
    self.en_passant = en_passant
    self.halfmove   = halfmove
    self.fullmove   = fullmove
  end 

  # @param str [String] the move to make in SAN
  # @return [PGN::Position] the resulting position
  #
  # @example
  #   queens_pawn = PGN::Position.start.move("d4")
  #
  def move(str)
    move       = PGN::Move.new(str, self.player)
    calculator = PGN::MoveCalculator.new(self.board, move)

    new_castling = self.castling - calculator.castling_restrictions
    new_halfmove = calculator.increment_halfmove? ?
      self.halfmove + 1 :
      0
    new_fullmove = calculator.increment_fullmove? ?
      self.fullmove + 1 :
      self.fullmove

    PGN::Position.new(
      calculator.result_board,
      self.next_player,
      new_castling,
      calculator.en_passant_square,
      new_halfmove,
      new_fullmove,
    )
  end

  # @return [Symbol] the next player to move
  #
  def next_player
    (PLAYERS - [self.player]).first
  end

  def inspect
    "\n" + self.board.inspect
  end

  # @return [PGN::FEN] a {PGN::FEN} object representing the current position
  #
  def to_fen
    PGN::FEN.from_attributes(
      board:      self.board,
      active:     self.player == :white ? 'w' : 'b',
      castling:   self.castling.join(''),
      en_passant: self.en_passant,
      halfmove:   self.halfmove.to_s,
      fullmove:   self.fullmove.to_s,
    )
  end

end

#halfmoveInteger



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
121
122
123
124
# File 'lib/pgn/position.rb', line 29

class Position
  PLAYERS  = [:white, :black]
  CASTLING = %w{K Q k q}

  attr_accessor :board
  attr_accessor :player
  attr_accessor :castling
  attr_accessor :en_passant
  attr_accessor :halfmove
  attr_accessor :fullmove

  # @return [PGN::Position] the starting position of a chess game
  #
  def self.start
    PGN::Position.new(
      PGN::Board.start,
      PLAYERS.first,
    )
  end

  # @param board [PGN::Board] the board for the position
  # @param player [Symbol] the player who moves next
  # @param castling [Array<String>] the castling moves that are still
  #   available
  # @param en_passant [String, nil] the en passant square if applicable
  # @param halfmove [Integer] the number of halfmoves since the last pawn
  #   move or capture
  # @param fullmove [Integer] the number of fullmoves made so far
  #
  # @example
  #   PGN::Position.new(
  #     PGN::Board.start,
  #     :white,
  #   )
  #
  def initialize(board, player, castling = CASTLING, en_passant = nil, halfmove = 0, fullmove = 1)
    self.board      = board
    self.player     = player
    self.castling   = castling
    self.en_passant = en_passant
    self.halfmove   = halfmove
    self.fullmove   = fullmove
  end 

  # @param str [String] the move to make in SAN
  # @return [PGN::Position] the resulting position
  #
  # @example
  #   queens_pawn = PGN::Position.start.move("d4")
  #
  def move(str)
    move       = PGN::Move.new(str, self.player)
    calculator = PGN::MoveCalculator.new(self.board, move)

    new_castling = self.castling - calculator.castling_restrictions
    new_halfmove = calculator.increment_halfmove? ?
      self.halfmove + 1 :
      0
    new_fullmove = calculator.increment_fullmove? ?
      self.fullmove + 1 :
      self.fullmove

    PGN::Position.new(
      calculator.result_board,
      self.next_player,
      new_castling,
      calculator.en_passant_square,
      new_halfmove,
      new_fullmove,
    )
  end

  # @return [Symbol] the next player to move
  #
  def next_player
    (PLAYERS - [self.player]).first
  end

  def inspect
    "\n" + self.board.inspect
  end

  # @return [PGN::FEN] a {PGN::FEN} object representing the current position
  #
  def to_fen
    PGN::FEN.from_attributes(
      board:      self.board,
      active:     self.player == :white ? 'w' : 'b',
      castling:   self.castling.join(''),
      en_passant: self.en_passant,
      halfmove:   self.halfmove.to_s,
      fullmove:   self.fullmove.to_s,
    )
  end

end

#playerSymbol

Returns the player who moves next.

Examples:

position.player #=> :white


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
121
122
123
124
# File 'lib/pgn/position.rb', line 29

class Position
  PLAYERS  = [:white, :black]
  CASTLING = %w{K Q k q}

  attr_accessor :board
  attr_accessor :player
  attr_accessor :castling
  attr_accessor :en_passant
  attr_accessor :halfmove
  attr_accessor :fullmove

  # @return [PGN::Position] the starting position of a chess game
  #
  def self.start
    PGN::Position.new(
      PGN::Board.start,
      PLAYERS.first,
    )
  end

  # @param board [PGN::Board] the board for the position
  # @param player [Symbol] the player who moves next
  # @param castling [Array<String>] the castling moves that are still
  #   available
  # @param en_passant [String, nil] the en passant square if applicable
  # @param halfmove [Integer] the number of halfmoves since the last pawn
  #   move or capture
  # @param fullmove [Integer] the number of fullmoves made so far
  #
  # @example
  #   PGN::Position.new(
  #     PGN::Board.start,
  #     :white,
  #   )
  #
  def initialize(board, player, castling = CASTLING, en_passant = nil, halfmove = 0, fullmove = 1)
    self.board      = board
    self.player     = player
    self.castling   = castling
    self.en_passant = en_passant
    self.halfmove   = halfmove
    self.fullmove   = fullmove
  end 

  # @param str [String] the move to make in SAN
  # @return [PGN::Position] the resulting position
  #
  # @example
  #   queens_pawn = PGN::Position.start.move("d4")
  #
  def move(str)
    move       = PGN::Move.new(str, self.player)
    calculator = PGN::MoveCalculator.new(self.board, move)

    new_castling = self.castling - calculator.castling_restrictions
    new_halfmove = calculator.increment_halfmove? ?
      self.halfmove + 1 :
      0
    new_fullmove = calculator.increment_fullmove? ?
      self.fullmove + 1 :
      self.fullmove

    PGN::Position.new(
      calculator.result_board,
      self.next_player,
      new_castling,
      calculator.en_passant_square,
      new_halfmove,
      new_fullmove,
    )
  end

  # @return [Symbol] the next player to move
  #
  def next_player
    (PLAYERS - [self.player]).first
  end

  def inspect
    "\n" + self.board.inspect
  end

  # @return [PGN::FEN] a {PGN::FEN} object representing the current position
  #
  def to_fen
    PGN::FEN.from_attributes(
      board:      self.board,
      active:     self.player == :white ? 'w' : 'b',
      castling:   self.castling.join(''),
      en_passant: self.en_passant,
      halfmove:   self.halfmove.to_s,
      fullmove:   self.fullmove.to_s,
    )
  end

end

Class Method Details

.startPGN::Position



42
43
44
45
46
47
# File 'lib/pgn/position.rb', line 42

def self.start
  PGN::Position.new(
    PGN::Board.start,
    PLAYERS.first,
  )
end

Instance Method Details

#inspectObject



107
108
109
# File 'lib/pgn/position.rb', line 107

def inspect
  "\n" + self.board.inspect
end

#move(str) ⇒ PGN::Position

Returns the resulting position.

Examples:

queens_pawn = PGN::Position.start.move("d4")


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/pgn/position.rb', line 79

def move(str)
  move       = PGN::Move.new(str, self.player)
  calculator = PGN::MoveCalculator.new(self.board, move)

  new_castling = self.castling - calculator.castling_restrictions
  new_halfmove = calculator.increment_halfmove? ?
    self.halfmove + 1 :
    0
  new_fullmove = calculator.increment_fullmove? ?
    self.fullmove + 1 :
    self.fullmove

  PGN::Position.new(
    calculator.result_board,
    self.next_player,
    new_castling,
    calculator.en_passant_square,
    new_halfmove,
    new_fullmove,
  )
end

#next_playerSymbol



103
104
105
# File 'lib/pgn/position.rb', line 103

def next_player
  (PLAYERS - [self.player]).first
end

#to_fenPGN::FEN



113
114
115
116
117
118
119
120
121
122
# File 'lib/pgn/position.rb', line 113

def to_fen
  PGN::FEN.from_attributes(
    board:      self.board,
    active:     self.player == :white ? 'w' : 'b',
    castling:   self.castling.join(''),
    en_passant: self.en_passant,
    halfmove:   self.halfmove.to_s,
    fullmove:   self.fullmove.to_s,
  )
end