Class: JustChess::SquareSet

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/just_chess/square_set.rb

Overview

Square Set

A collection of Squares with useful filtering functions

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(squares:) ⇒ SquareSet

New objects can be instantiated by passing in a hash with squares. They can be square objects or hashes.

Example:

# Instantiates a new Square Set
JustChess::SquareSet.new({
  squares: [
    { x: 1, y: 0, piece: { player_number: 1, direction: 1, king: false }}
  ]
})

Parameters:

  • squares (Array<Square,Hash>)

    An array of squares, each with x and y co-ordinates and a piece.



25
26
27
28
29
30
31
32
33
# File 'lib/just_chess/square_set.rb', line 25

def initialize(squares: )
  @squares = if squares.all? { |s| s.instance_of?(Hash) }
    squares.map { |s| Square.new(s) }
  elsif squares.all? { |s| s.instance_of?(Square) }
    squares
  else
    raise ArgumentError, "all squares must have the same class"
  end
end

Instance Attribute Details

#squaresArray<Square> (readonly)

Returns The squares in the set.

Returns:

  • (Array<Square>)

    The squares in the set.



36
37
38
# File 'lib/just_chess/square_set.rb', line 36

def squares
  @squares
end

Instance Method Details

#&(other) ⇒ SquareSet

Find the intersection of Squares between sets

Example:

# Find the intersection of Squares
square_set & other

Parameters:

Returns:



101
102
103
# File 'lib/just_chess/square_set.rb', line 101

def &(other)
  select { |square| other.include?(square) }
end

#+(other) ⇒ SquareSet

Concat two SquareSets together

Example:

# Concat two SquareSets together
square_set + other

Parameters:

Returns:



56
57
58
59
60
# File 'lib/just_chess/square_set.rb', line 56

def +(other)
  _squares = squares + other.squares

  self.class.new(squares: _squares)
end

#-(other) ⇒ SquareSet

Remove squares from one SquareSet from another

Example:

# Remove squares from one SquareSet
square_set - other

Parameters:

Returns:



71
72
73
74
75
# File 'lib/just_chess/square_set.rb', line 71

def -(other)
  _squares = squares - other.squares

  self.class.new(squares: _squares)
end

#<<(square) ⇒ SquareSet

Push a Square onto a SquareSet

Example:

# Push a Square onto a SquareSet
square_set << square

Parameters:

  • square (Square)

    the square being pushed on

Returns:



86
87
88
89
90
# File 'lib/just_chess/square_set.rb', line 86

def <<(square)
  _squares = squares << square

  self.class.new(squares: _squares)
end

#as_jsonHash

serializes the squares as a hash

Returns:

  • (Hash)


403
404
405
# File 'lib/just_chess/square_set.rb', line 403

def as_json
  squares.map(&:as_json)
end

#at_range(square, distance) ⇒ SquareSet

Find all squares at distance of square

Example:

# Get all squares at 2 squares from square_a
square_set.at_range(square_a, 2)

Parameters:

  • square (Square)

    the originating square

  • distance (Fixnum)

    the specified distance from the square

Returns:



234
235
236
# File 'lib/just_chess/square_set.rb', line 234

def at_range(square, distance)
  select { |s| Vector.new(square, s).magnitude.abs == distance }
end

#between(a, b) ⇒ SquareSet

Returns squares between a and b. Only squares that are in the same diagonal will return squares.

Example:

# Get all squares between square_a and square_b
square_set.between(square_a, square_b)

Parameters:

Returns:



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/just_chess/square_set.rb', line 184

def between(a, b)
  vector = Vector.new(a, b)

  if vector.diagonal? || vector.orthogonal?
    point_counter = a.point
    direction = vector.direction
    _squares = []

    while point_counter != b.point
      point_counter = point_counter + direction
      square = find_by_x_and_y(point_counter.x, point_counter.y)
      if square && square.point != b.point
        _squares.push(square)
      end
    end
  else
    _squares = []
  end

  self.class.new(squares: _squares)
end

#diagonal(square) ⇒ SquareSet

Find all squares diagonal from square

Example:

# Get all squares diagonal from square_a
square_set.diagonal(square_a)

Parameters:

  • square (Square)

    the originating square

Returns:



276
277
278
# File 'lib/just_chess/square_set.rb', line 276

def diagonal(square)
  select { |s| Vector.new(square, s).diagonal? }
end

#excluding_piece(piece_type) ⇒ SquareSet

Find all squares occupied by a piece not of a particular type

Parameters:

  • piece_type (Class)

    the class of the piece.

Returns:



359
360
361
# File 'lib/just_chess/square_set.rb', line 359

def excluding_piece(piece_type)
  select { |s| s.piece && !s.piece.is_a?(piece_type) }
end

#find_by_id(id) ⇒ Square

Find the square with the matching unique identifier

Example:

# Find the square with id 4
square_set.find_by_id(4)

Parameters:

  • id (Fixnum)

    the unique identifier.

Returns:



124
125
126
# File 'lib/just_chess/square_set.rb', line 124

def find_by_id(id)
  find { |s| s.id == id }
end

#find_by_piece_id(piece_id) ⇒ Square

Find the square with the matching piece identifier

Example:

# Find the square with a piece of id 4
square_set.find_by_piece_id(4)

Parameters:

  • piece_id (Fixnum)

    the unique identifier of the piece.

Returns:



153
154
155
# File 'lib/just_chess/square_set.rb', line 153

def find_by_piece_id(piece_id)
  find { |s| s.piece && s.piece.id == piece_id }
end

#find_by_x_and_y(x, y) ⇒ Square

Find the square with the matching x and y co-ordinates

Example:

# Find the square at 4,2
square_set.find_by_x_and_y(4, 2)

Parameters:

  • x (Fixnum)

    the x co-ordinate.

  • y (Fixnum)

    the y co-ordinate.

Returns:



140
141
142
# File 'lib/just_chess/square_set.rb', line 140

def find_by_x_and_y(x, y)
  find { |s| s.x == x && s.y == y }
end

#find_king_for_player(player_number) ⇒ Square

Find the square occupied by the player’s king

Example:

# Find the square occupied by player 2's king
square_set.find_king_for_player(2)

Parameters:

  • player_number (Fixnum)

    the number of the player

Returns:



166
167
168
# File 'lib/just_chess/square_set.rb', line 166

def find_king_for_player(player_number)
  find { |s| s.piece && s.piece.is_a?(JustChess::King) && s.occupied_by_player?(player_number) }
end

#in_direction(square, direction_y) ⇒ SquareSet

Find all squares in the y direction of square

Example:

# Get all squares up from square_a
square_set.in_direction(square_a, -1)

Parameters:

  • square (Square)

    the originating square

  • direction_y (Fixnum)

    the direction, either up (-1) or down (1)

Returns:



250
251
252
# File 'lib/just_chess/square_set.rb', line 250

def in_direction(square, direction_y)
  select { |s| Vector.new(square, s).direction.y == direction_y }
end

#in_range(square, distance) ⇒ SquareSet

Find all squares within distance of square

Example:

# Get all squares within 2 squares of square_a
square_set.in_range(square_a, 2)

Parameters:

  • square (Square)

    the originating square

  • distance (Fixnum)

    the specified distance from the square

Returns:



218
219
220
# File 'lib/just_chess/square_set.rb', line 218

def in_range(square, distance)
  select { |s| Vector.new(square, s).magnitude.abs <= distance }
end

#not_orthogonal_or_diagonal(square) ⇒ SquareSet

Find all squares not orthogonal or diagonal from square

Example:

# Get all squares not orthogonal or diagonal from square_a
square_set.not_orthogonal_or_diagonal(square_a)

Parameters:

  • square (Square)

    the originating square

Returns:



302
303
304
# File 'lib/just_chess/square_set.rb', line 302

def not_orthogonal_or_diagonal(square)
  select { |s| Vector.new(square, s).not_orthogonal_or_diagonal? }
end

#occupied_by_opponent(player_number) ⇒ SquareSet

Takes a player number and returns all squares occupied by the opponent of the player

Parameters:

  • player_number (Fixnum)

    the player’s number.

Returns:



329
330
331
# File 'lib/just_chess/square_set.rb', line 329

def occupied_by_opponent(player_number)
  select { |s| s.occupied_by_opponent?(player_number) }
end

#occupied_by_piece(piece_type) ⇒ SquareSet

Find all squares occupied by a piece of a particular type

Parameters:

  • piece_type (Class)

    the class of the piece.

Returns:



349
350
351
# File 'lib/just_chess/square_set.rb', line 349

def occupied_by_piece(piece_type)
  select { |s| s.piece && s.piece.is_a?(piece_type) }
end

#occupied_by_player(player_number) ⇒ SquareSet

Takes a player number and returns all squares occupied by the player

Parameters:

  • player_number (Fixnum)

    the player’s number.

Returns:



319
320
321
# File 'lib/just_chess/square_set.rb', line 319

def occupied_by_player(player_number)
  select { |s| s.occupied_by_player?(player_number) }
end

#orthogonal(square) ⇒ SquareSet

Find all squares orthogonal from square

Example:

# Get all squares orthogonal from square_a
square_set.orthogonal(square_a)

Parameters:

  • square (Square)

    the originating square

Returns:



263
264
265
# File 'lib/just_chess/square_set.rb', line 263

def orthogonal(square)
  select { |s| Vector.new(square, s).orthogonal? }
end

#orthogonal_or_diagonal(square) ⇒ SquareSet

Find all squares orthogonal or diagonal from square

Example:

# Get all squares orthogonal or diagonal from square_a
square_set.orthogonal_or_diagonal(square_a)

Parameters:

  • square (Square)

    the originating square

Returns:



289
290
291
# File 'lib/just_chess/square_set.rb', line 289

def orthogonal_or_diagonal(square)
  select { |s| Vector.new(square, s).orthogonal_or_diagonal? }
end

#select(&block) ⇒ SquareSet

Filter the squares with a block and behaves like Enumerable#select. It returns a SquareSet with the filtered squares.

Returns:



109
110
111
112
113
# File 'lib/just_chess/square_set.rb', line 109

def select(&block)
  _squares = squares.select(&block)

  self.class.new(squares: _squares)
end

#threatened_by(player_number, game_state) ⇒ SquareSet

Returns all squares threatened by the specified player

Parameters:

  • player_number (Fixnum)

    the player’s number.

  • game_state (GameState)

    the current game state.

Returns:



392
393
394
395
396
397
398
# File 'lib/just_chess/square_set.rb', line 392

def threatened_by(player_number, game_state)
  _squares = occupied_by_player(player_number).map do |s|
    s.piece.capture_squares(s, game_state).squares
  end.flatten.uniq

  self.class.new(squares: _squares)
end

#unblocked(origin, square_set) ⇒ SquareSet

Returns destination from the origin that have a clear path

Parameters:

  • origin (Square)

    the originating square.

  • square_set (SquareSet)

    the board position.

Returns:



372
373
374
# File 'lib/just_chess/square_set.rb', line 372

def unblocked(origin, square_set)
  select { |destination| square_set.between(origin, destination).all?(&:unoccupied?) }
end

#unmovedSquareSet

Returns all squares with pieces that haven’t moved

Returns:



379
380
381
# File 'lib/just_chess/square_set.rb', line 379

def unmoved
  select { |s| s.piece && s.piece.has_not_moved? }
end

#unoccupiedSquareSet

Find all squares without pieces on them.

Returns:



309
310
311
# File 'lib/just_chess/square_set.rb', line 309

def unoccupied
  select { |s| s.unoccupied? }
end

#unoccupied_or_occupied_by_opponent(player_number) ⇒ SquareSet

Takes a player number and returns all squares unoccupied or occupied by the opponent of the player

Parameters:

  • player_number (Fixnum)

    the player’s number.

Returns:



339
340
341
# File 'lib/just_chess/square_set.rb', line 339

def unoccupied_or_occupied_by_opponent(player_number)
  select { |s| s.unoccupied? || s.occupied_by_opponent?(player_number) }
end