class JustGo::GameState

Game State

Represents a game of Go in progress.

Constants

BOARD_SIZE

Attributes

current_player_number[R]
errors[R]
last_change[R]
player_stats[R]
points[R]
previous_state[R]

Public Class Methods

default() click to toggle source
# File lib/just_go/game_state.rb, line 33
def self.default
  self.new(
    current_player_number: 1,
    points: BOARD_SIZE.times.map do |row|
      BOARD_SIZE.times.map do |col|
        { 
          id: row*BOARD_SIZE + col, 
          x: col, 
          y: row, 
          stone: nil
        }
      end
    end.flatten,
    previous_state: nil,
    player_stats: [
      { player_number: 1, prisoner_count: 0, passed: false },
      { player_number: 2, prisoner_count: 0, passed: false }
    ]
  )
end
new(current_player_number: , points: , previous_state: nil, player_stats: []) click to toggle source
# File lib/just_go/game_state.rb, line 17
def initialize(current_player_number: , points: , previous_state: nil, player_stats: [])
  @current_player_number = current_player_number
  @points = JustGo::PointSet.new(points: points)
  @previous_state = previous_state
  @player_stats = player_stats.map { |ps| JustGo::PlayerStat.new(**ps) }
  @errors = []
  @last_change = {}
end

Public Instance Methods

as_json() click to toggle source
# File lib/just_go/game_state.rb, line 54
def as_json
  {
    current_player_number: current_player_number,
    points: points.as_json,
    previous_state: previous_state,
    player_stats: player_stats.map(&:as_json)
  }
end
move(player_number, point_id) click to toggle source
# File lib/just_go/game_state.rb, line 63
def move(player_number, point_id)
  @errors = []

  point = points.find_by_id(point_id.to_i)

  if current_player_number != player_number
    @errors.push JustGo::NotPlayersTurnError.new
  elsif point.nil?
    @errors.push JustGo::PointNotFoundError.new
  elsif point.occupied? 
    @errors.push JustGo::PointNotEmptyError.new
  elsif points.liberties_for(point).zero? && points.deprives_liberties?(point, player_number) && !points.deprives_opponents_liberties?(point, player_number)
    @errors.push JustGo::NoLibertiesError.new
  else
    dupped = points.dup
    dupped.perform_move(point, player_number)

    if dupped.minify == @previous_state
      @errors.push JustGo::KoRuleViolationError.new 
    else
      @player_stats.detect { |p| p.player_number == next_player_number }.mark_as_continuing 
      
      @previous_state = points.minify

      stone_count = points.perform_move(point, player_number)

      @player_stats.detect { |pc| pc.player_number == player_number }.add_to_prisoner_count(stone_count)

      pass_turn
    end
  end
  
  errors.empty?
end
pass(player_number) click to toggle source
# File lib/just_go/game_state.rb, line 98
def pass(player_number)
  if current_player_number != player_number
    @errors.push JustGo::NotPlayersTurnError.new
  else
    @player_stats.detect { |ps| ps.player_number == player_number }.mark_as_passed 
    next_player_passed = @player_stats.detect { |ps| ps.player_number == next_player_number }.passed 
    if next_player_passed 
      points.mark_territories
    else
      pass_turn
    end
  end

  errors.empty?
end
score() click to toggle source
# File lib/just_go/game_state.rb, line 114
def score
  [
    { player_number: 1, score: player_score(1) },
    { player_number: 2, score: player_score(2) }
  ]
end
winner() click to toggle source
# File lib/just_go/game_state.rb, line 121
def winner
  if @player_stats.map { |ps| ps.passed }.all?
    score.max_by { |line| line[:score] }[:player_number]
  else
    nil
  end
end

Private Instance Methods

next_player_number() click to toggle source
# File lib/just_go/game_state.rb, line 147
def next_player_number
  current_player_number == 1 ? 2 : 1
end
pass_turn() click to toggle source
# File lib/just_go/game_state.rb, line 143
def pass_turn
  @current_player_number = next_player_number 
end
player_score(player_number) click to toggle source
# File lib/just_go/game_state.rb, line 131
def player_score(player_number)
  prisoner_count(player_number) + territory_count(player_number) 
end
prisoner_count(player_number) click to toggle source
# File lib/just_go/game_state.rb, line 135
def prisoner_count(player_number)
  player_stats.detect { |ps| ps.player_number == player_number }.prisoner_count
end
territory_count(player_number) click to toggle source
# File lib/just_go/game_state.rb, line 139
def territory_count(player_number)
  points.territories_for(player_number).sum(&:size)
end