class JustGo::PointSet
PointSet
¶ ↑
A collection of Points with useful filtering functions
Attributes
points[R]
Public Class Methods
new(points: [])
click to toggle source
# File lib/just_go/point_set.rb, line 15 def initialize(points: []) @points = case when !points.is_a?(Array) raise ArgumentError, 'points must be an array of Hash or Point' when points.all? { |p| p.is_a?(Hash) } points.map { |p| JustGo::Point.new(**p) } when points.all? { |p| p.is_a?(JustGo::Point) } points else raise ArgumentError, 'points must be an array of Hash or Point' end end
Public Instance Methods
adjacent(point_or_group)
click to toggle source
# File lib/just_go/point_set.rb, line 69 def adjacent(point_or_group) case point_or_group when JustGo::Point select do |p| vector = JustGo::Vector.new(point_or_group, p) vector.orthogonal? && vector.magnitude == 1 end when JustGo::Chain _points = point_or_group.points.map do |p| adjacent(p).points end.flatten.reject do |p| point_or_group.include?(p) end.uniq do |p| p.id end self.class.new(points: _points) when JustGo::Territory _points = point_or_group.points.map do |p| adjacent(p).points end.flatten.reject do |p| point_or_group.include?(p) end.uniq do |p| p.id end self.class.new(points: _points) else raise ArgumentError, 'Must be Point or Chain or Territory' end end
adjacent_chain_id(point, player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 203 def adjacent_chain_id(point, player_number) adjacent(point).occupied_by(player_number).map { |p| p.stone.chain_id }.first end
as_json()
click to toggle source
# File lib/just_go/point_set.rb, line 36 def as_json points.map(&:as_json) end
build_stone(point, player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 211 def build_stone(point, player_number) JustGo::Stone.new( id: next_stone_id, player_number: player_number, chain_id: adjacent_chain_id(point, player_number) || next_chain_id ) end
capture_stones(player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 172 def capture_stones(player_number) stone_count = 0 chains.select do |c| c.player_number != player_number && liberties_for(c) == 0 end.each do |c| c.points.each do |p| p.capture_stone stone_count += 1 end end stone_count end
chains(chain_ids=nil)
click to toggle source
# File lib/just_go/point_set.rb, line 116 def chains(chain_ids=nil) if chain_ids chain_ids.map do |c_id| _points = select { |p| p.stone && p.stone.chain_id == c_id }.points JustGo::Chain.new(points: _points) end else all_chain_ids = select { |p| p.stone }.map { |p| p.stone.chain_id }.uniq chains(all_chain_ids) end end
deprives_liberties?(point, player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 148 def deprives_liberties?(point, player_number) chain_ids = adjacent(point).occupied_by(player_number).map { |p| p.stone.chain_id }.uniq _chains = chains(chain_ids) _chains.all? { |c| liberties_for(c) == 1 } end
deprives_opponents_liberties?(point, player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 154 def deprives_opponents_liberties?(point, player_number) chain_ids = adjacent(point).occupied_by_opponent(player_number).map { |p| p.stone.chain_id }.uniq _chains = chains(chain_ids) _chains.any? { |c| liberties_for(c) == 1 } end
dup()
click to toggle source
# File lib/just_go/point_set.rb, line 226 def dup self.class.new(points: as_json) end
find_by_id(point_id)
click to toggle source
# File lib/just_go/point_set.rb, line 45 def find_by_id(point_id) find { |p| p.id == point_id } end
find_by_x_and_y(x, y)
click to toggle source
# File lib/just_go/point_set.rb, line 49 def find_by_x_and_y(x, y) find { |p| p.x == x && p.y == y } end
liberties_for(point_or_chain)
click to toggle source
# File lib/just_go/point_set.rb, line 144 def liberties_for(point_or_chain) adjacent(point_or_chain).unoccupied.size end
mark_territories()
click to toggle source
# File lib/just_go/point_set.rb, line 230 def mark_territories points.each(&:clear_territory) points.each do |point| if point.unoccupied? && point.unmarked? territory_ids = adjacent(point).unoccupied.map(&:territory_id).compact add_territory_id = case territory_ids.size when 0 (points.map(&:territory_id).compact.max || 0) + 1 when 1 territory_ids.first else min_id, *other_ids = territory_ids.sort where(territory_id: other_ids).each do |other_point| other_point.add_to_territory(min_id) end min_id end point.add_to_territory(add_territory_id) end end end
minify()
click to toggle source
# File lib/just_go/point_set.rb, line 187 def minify points.map do |p| player_number = p.stone && p.stone.player_number player_number ? player_number.to_s : '-' end.join end
next_chain_id()
click to toggle source
# File lib/just_go/point_set.rb, line 207 def next_chain_id (occupied.map { |p| p.stone.chain_id }.max || 0) + 1 end
next_stone_id()
click to toggle source
# File lib/just_go/point_set.rb, line 199 def next_stone_id (occupied.map { |p| p.stone.id }.max || 0) + 1 end
occupied()
click to toggle source
# File lib/just_go/point_set.rb, line 53 def occupied select(&:occupied?) end
occupied_by(player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 61 def occupied_by(player_number) select { |p| p.occupied_by?(player_number) } end
occupied_by_opponent(player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 65 def occupied_by_opponent(player_number) select { |p| p.occupied_by_opponent?(player_number) } end
perform_move(point, player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 219 def perform_move(point, player_number) stone = build_stone(point, player_number) place(point.id, stone) update_joined_chains(point.id, player_number) capture_stones(player_number) end
place(point_id, stone)
click to toggle source
# File lib/just_go/point_set.rb, line 194 def place(point_id, stone) point = find_by_id(point_id) point.place(stone) end
select(&block)
click to toggle source
# File lib/just_go/point_set.rb, line 40 def select(&block) _points = points.select(&block) self.class.new(points: _points) end
territories(territory_ids=nil)
click to toggle source
# File lib/just_go/point_set.rb, line 128 def territories(territory_ids=nil) if territory_ids territory_ids.map do |t_id| _points = select { |p| p.territory_id == t_id }.points JustGo::Territory.new(points: _points) end else all_territory_ids = select(&:territory_id).map(&:territory_id).uniq territories(all_territory_ids) end end
territories_for(player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 140 def territories_for(player_number) territories.select { |t| adjacent(t).all? { |p| p.occupied_by?(player_number) } } end
unoccupied()
click to toggle source
# File lib/just_go/point_set.rb, line 57 def unoccupied select(&:unoccupied?) end
update_joined_chains(point_id, player_number)
click to toggle source
# File lib/just_go/point_set.rb, line 160 def update_joined_chains(point_id, player_number) point = find_by_id(point_id) existing_chain_ids = adjacent(point).occupied_by(player_number).map { |p| p.stone.chain_id }.uniq existing_chains = chains(existing_chain_ids) existing_chains.each do |c| c.points.each do |p| p.stone.join_chain(point.stone) end end end
where(args)
click to toggle source
# File lib/just_go/point_set.rb, line 101 def where(args) scope = self args.each do |field, value| scope = scope.select do |p| case value when Array value.include?(p.send(field)) else p.send(field) == value end end end scope end