Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 135 lines (118 sloc) 3.497 kb
229c144 @ryanb major refactoring to game engine and worker
authored
1 class GameEngine
2 class Error < StandardError; end
3 class IllegalMove < Error; end
4 class OutOfTurn < Error; end
5
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
6 def self.run(options = {})
229c144 @ryanb major refactoring to game engine and worker
authored
7 Go::GTP.run_gnugo do |gtp|
8 gtp.boardsize(options[:board_size]) unless options[:board_size].to_s.empty?
9 gtp.fixed_handicap(options[:handicap]) if options[:handicap].to_i.nonzero?
10 gtp.komi(options[:komi]) unless options[:komi].to_s.empty?
11 yield GameEngine.new(gtp, options)
12 end
13 end
14
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
15 def self.update_game_attributes_with_move(game, move = nil)
16 update = {}
17 run(game) do |engine|
18 update.merge!(engine.update_game_attributes_with_move(game, move))
19 end
20 update
21 end
22
229c144 @ryanb major refactoring to game engine and worker
authored
23 def initialize(gtp, options = {})
33b5a3d @ryanb handle score better when resigning
authored
24 @resigned = nil
229c144 @ryanb major refactoring to game engine and worker
authored
25 @gtp = gtp
26 @board_size = options[:board_size] || 19
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
27 @handicap = options[:handicap].to_i
28 @current_color = @handicap > 0 ? :white : :black
229c144 @ryanb major refactoring to game engine and worker
authored
29 end
30
31 def replay(moves)
32 moves.to_s.split("-").each do |move|
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
33 play(move =~ /[A-Z]/ ? move : move[0..1])
229c144 @ryanb major refactoring to game engine and worker
authored
34 end
35 end
36
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
37 # Play at the given position, nil for computer play
38 def play(position = nil)
39 if position.nil?
40 position = sgf_point(@gtp.genmove(@current_color))
7d32b9a @ryanb report the game is over when computer resigns
authored
41 else
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
42 @gtp.play(@current_color, gnugo_point(position)) unless position == "RESIGN"
43 raise IllegalMove unless @gtp.success?
7d32b9a @ryanb report the game is over when computer resigns
authored
44 end
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
45 if position == "RESIGN"
46 @resigned = @current_color
47 end
48 @current_color = opposite_color
49 position
229c144 @ryanb major refactoring to game engine and worker
authored
50 end
51
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
52 # Play the move and include the captured stones afterwards
53 def move(position = nil)
7d32b9a @ryanb report the game is over when computer resigns
authored
54 raise IllegalMove if over?
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
55 if %w[PASS RESIGN].include? position
56 play(position)
229c144 @ryanb major refactoring to game engine and worker
authored
57 else
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
58 other_color = opposite_color
59 other_stones = @gtp.list_stones(other_color)
60 position = play(position)
61 captured = other_stones - @gtp.list_stones(other_color)
62 position + captured.map { |v| sgf_point(v) }.join
229c144 @ryanb major refactoring to game engine and worker
authored
63 end
64 end
65
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
66 def update_game_attributes_with_move(game, move = nil)
67 update = {}
68 replay(game[:moves])
69 update[:moves] = [game[:moves].to_s, move(move)].reject(&:empty?).join("-")
70 update[:last_move_at] = Time.now
71 update[:black_positions] = positions(:black)
72 update[:white_positions] = positions(:white)
73 update[:current_player_id] = game["#{@current_color}_player_id".to_sym]
74 if over?
75 update[:finished_at] = Time.now
76 update[:black_score] = score(:black)
77 update[:white_score] = score(:white)
78 else
79 update[:black_score] = captures(:black)
80 update[:white_score] = captures(:white)
81 end
82 update
83 end
84
229c144 @ryanb major refactoring to game engine and worker
authored
85 def positions(color)
86 @gtp.list_stones(color).map { |v| sgf_point(v) }.join
87 end
88
89 def captures(color)
90 @gtp.captures(color)
91 end
92
7d32b9a @ryanb report the game is over when computer resigns
authored
93 def over?
dc46756 @ryanb allow player to resign
authored
94 @resigned || @gtp.over?
229c144 @ryanb major refactoring to game engine and worker
authored
95 end
96
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
97 def score(color)
33b5a3d @ryanb handle score better when resigning
authored
98 if @resigned
99 @resigned.to_sym == color.to_sym ? 0 : 1
100 else
101 @gtp.final_score[/^#{color.to_s[0].upcase}\+([\d\.]+)$/, 1].to_f
102 end
229c144 @ryanb major refactoring to game engine and worker
authored
103 end
104
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
105 private
106
107 def opposite_color
108 @current_color == :black ? :white : :black
229c144 @ryanb major refactoring to game engine and worker
authored
109 end
110
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
111 def point(position)
112 args = [position]
113 if position =~ /\A[A-HJ-T](?:1\d|[1-9])\z/
229c144 @ryanb major refactoring to game engine and worker
authored
114 args << {:board_size => @board_size}
115 end
116 Go::GTP::Point.new(*args)
117 end
118
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
119 def gnugo_point(position)
120 if %w[PASS RESIGN].include? position.to_s.upcase
121 position.to_s.upcase
229c144 @ryanb major refactoring to game engine and worker
authored
122 else
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
123 point(position).to_gnugo(@board_size)
229c144 @ryanb major refactoring to game engine and worker
authored
124 end
125 end
126
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
127 def sgf_point(position)
128 if %w[PASS RESIGN].include? position.to_s.upcase
129 position.to_s.upcase
229c144 @ryanb major refactoring to game engine and worker
authored
130 else
50d2a28 @ryanb moving a lot of logic into the game model to remove duplication with …
authored
131 point(position).to_sgf
229c144 @ryanb major refactoring to game engine and worker
authored
132 end
133 end
134 end
Something went wrong with that request. Please try again.