reversi 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c602bf3c1c6a4dc238b2a168a769f4b46a5727f
4
- data.tar.gz: 88313f627c8fef5882dbfa5829c225ff0a1e3e0b
3
+ metadata.gz: f21066f809daeaccbfdfbc19f61dc5ac79b0dbca
4
+ data.tar.gz: dca98c6b7c7f64ae612e35dd3a218a9993b35434
5
5
  SHA512:
6
- metadata.gz: 409dcbf84198f1f7e0bff93e3314a5cf6b6126381eca11fff4d65260fcf4c4bb31931ef0082268737cfa63720aa497179074d6856fbf08f2afea13bdfd124d9e
7
- data.tar.gz: fa549524250d3431623f06ac0bcdd7746032a388f8c546fb759913ec1ec63927147e19b119574a25603c41c1900ccec560cf5ba353ebeb903d1dd8b539a6ce46
6
+ metadata.gz: 0b6798e66984df642eb6fec17b0bf88a6d37d21c10b909558d6ca069a0fab63e347a76fc01106cf7993bf23f468c62da060a296341792b1058bedaa682d4eaee
7
+ data.tar.gz: ae1a412572613d73f47b75aed52c63211f50b90d2a3a0f22d7a8d86a7b9dcf586553d25bf2792b708eb4215c864513c102febc43519eae4ce241c194fdd529e1
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Reversi
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/reversi.svg)](http://badge.fury.io/rb/reversi) [![Build Status](https://travis-ci.org/seinosuke/reversi.svg?branch=master)](https://travis-ci.org/seinosuke/reversi)
3
+ [![Gem Version](https://badge.fury.io/rb/reversi.svg)](http://badge.fury.io/rb/reversi) [![Build Status](https://travis-ci.org/seinosuke/reversi.svg?branch=master)](https://travis-ci.org/seinosuke/reversi) [![Inline docs](http://inch-ci.org/github/seinosuke/reversi.svg?branch=master)](http://inch-ci.org/github/seinosuke/reversi)
4
4
  A Ruby Gem to play reversi game. You can enjoy a game on the command line or easily make your original reversi game programs.
5
5
 
6
6
  ![reversi.gif](https://github.com/seinosuke/reversi/blob/master/images/reversi.gif)
@@ -53,19 +53,22 @@ Use `Reversi.configure` to configure setting for a reversi game.
53
53
  * `disk_w` A string of the black disks. ( 'w' )
54
54
  * `disk_color_b` A color of the black disks. ( 0 )
55
55
  * `disk_color_w` A color of the black disks. ( 0 )
56
- * `initial_position` The initial positions of each disk on the board. ( {:black => [[:d, 5], [:e, 4]], :white => [[:d, 4], [:e, 5]]} )
56
+ * `initial_position` The initial positions of each disk on the board.
57
57
  * `progress` Whether or not the progress of the game is displayed. ( false )
58
58
  * `stack_limit` The upper limit number of times of use repeatedly `Reversi::Board#undo!` . ( 3 )
59
59
 
60
60
  A string and a color of the disks are reflected on `game.board.to_s` .
61
61
  You can choose from 9 colors, black, red, green, yellow, blue, magenda, cyan, white and gray.
62
62
 
63
+ The default of `initial_position` is `{:black => [[4, 5], [5, 4]], :white => [[4, 4], [5, 5]]}` .
64
+
63
65
  Using `Reversi.reset` method, you can reset all options to the default values.
64
66
 
65
67
  ### Human vs Computer
66
68
 
67
69
  Set `Reversi::Player::Human` to player_b or player_w, and run. Please input your move (for example: d3). This program is terminated when this game is over or when you input `q` or `exit`.
68
70
 
71
+
69
72
  ```ruby
70
73
  Reversi.configure do |config|
71
74
  config.player_b = Reversi::Player::Human
@@ -75,13 +78,14 @@ game = Reversi::Game.new
75
78
  game.start
76
79
  ```
77
80
 
81
+
78
82
  ### Your Original Player
79
83
 
80
84
  You can make your original player class by inheriting `Reversi::Player::BasePlayer` and defining `move` method.
81
85
 
82
- `next_moves` method returns an array of the next moves information. A player places a supplied color's disk on specified position, and flips the opponent's disks by using `put_disk` method. You can get the current game board state from a `board` variable.
86
+ `next_moves` method returns an array of the next moves information. A player places a supplied color's disk on specified position, and flips the opponent's disks by using `put_disk` method. You can get the current game board state from a `board` variable or `status` method.
83
87
 
84
- * Example of Random AI
88
+ * **Example of Random Player**
85
89
 
86
90
  ```ruby
87
91
  class MyAI < Reversi::Player::BasePlayer
@@ -99,8 +103,78 @@ game = Reversi::Game.new
99
103
  game.start
100
104
  ```
101
105
 
102
- * Other examples of algorithm
103
- Please see [Reversi::Player::MinMaxAI](https://github.com/seinosuke/reversi/blob/master/lib/reversi/player/min_max_ai.rb) or [Reversi::Player::NegaMaxAI](https://github.com/seinosuke/reversi/blob/master/lib/reversi/player/nega_max_ai.rb) . These are examples of the player that can read the next three moves and evaluate a game state based on the positions of the disks. If you want to read the next more than three moves, set `stack_limit` to the number.
106
+ * **Example of MinMax algorithm**
107
+
108
+ ```ruby
109
+ class MyAI < Reversi::Player::BasePlayer
110
+
111
+ def initialize(_color, _board)
112
+ super
113
+
114
+ # The evaluation value at each position.
115
+ points = [
116
+ 100, -10, 0, -1, -1, 0, -10, 100,
117
+ -10, -30, -5, -5, -5, -5, -30, -10,
118
+ 0, -5, 0, -1, -1, 0, -5, 0,
119
+ -1, -5, -1, -1, -1, -1, -5, -1,
120
+ -1, -5, -1, -1, -1, -1, -5, -1,
121
+ 0, -5, 0, -1, -1, 0, -5, 0,
122
+ -10, -30, -5, -5, -5, -5, -30, -10,
123
+ 100, -10, 0, -1, -1, 0, -10, 100
124
+ ]
125
+ @evaluation_value =
126
+ Hash[(1..8).map{ |x| (1..8).map{ |y| [[x, y], points.shift] } }.flatten(1) ]
127
+ end
128
+
129
+ def move(board)
130
+ moves = next_moves.map{ |v| v[:move] }
131
+ return if moves.empty?
132
+ next_move = moves.map do |move|
133
+ { :move => move, :point => evaluate(move, board, 3, true) }
134
+ end.max_by{ |v| v[:point] }[:move]
135
+ put_disk(*next_move)
136
+ end
137
+
138
+ def evaluate(move, board, depth, color)
139
+ # Move to the child node.
140
+ put_disk(*move, color)
141
+
142
+ # Acquire the branches of this node.
143
+ moves = next_moves(!color).map{ |v| v[:move] }
144
+
145
+ # Evaluate a current game-state when a search reaches the leaf node.
146
+ if depth == 1
147
+ status[:mine].inject(0){ |sum, xy| sum + @evaluation_value[xy] }
148
+ elsif moves.empty?
149
+ -100
150
+
151
+ # Select one of the child nodes
152
+ # when the current node is not the leaf node.
153
+ # Return a minimum value if it is a my move, or
154
+ # return a maximum value if it is an opponent's move.
155
+ else
156
+ values = moves.map{ |move| evaluate(move, board, depth - 1, !color) }
157
+ case depth
158
+ when ->(n){ n.odd? } then values.min
159
+ when ->(n){ n.even? } then values.max end
160
+ end
161
+
162
+ # Return to a parent node.
163
+ ensure
164
+ board.undo!
165
+ end
166
+ end
167
+
168
+ Reversi.configure do |config|
169
+ config.player_b = MyAI
170
+ end
171
+
172
+ game = Reversi::Game.new
173
+ game.start
174
+ ```
175
+
176
+ * **Other examples of algorithm**
177
+ Please see [Reversi::Player::NegaMaxAI](https://github.com/seinosuke/reversi/blob/master/lib/reversi/player/nega_max_ai.rb) or [Reversi::Player::AlphaBetaAI](https://github.com/seinosuke/reversi/blob/master/lib/reversi/player/alpha_beta_ai.rb) . These are examples of the player that can read the next three moves and evaluate a game state based on the positions of the disks. If you want to read the next more than three moves, set `stack_limit` to the number.
104
178
 
105
179
  ## Contributing
106
180
 
@@ -1,16 +1,31 @@
1
1
  #include "reversi.h"
2
2
 
3
+ struct stack{
4
+ int stack_columns[10][10];
5
+ struct stack *next;
6
+ };
7
+
8
+ struct stack *head = NULL;
9
+
10
+ struct board {
11
+ int columns[10][10];
12
+ };
13
+
3
14
  void Init_reversi(void) {
4
15
  VALUE reversi = rb_define_module("Reversi");
5
16
  VALUE reversi_board = rb_define_class_under(reversi, "Board", rb_cObject);
6
17
 
7
18
  rb_define_alloc_func(reversi_board, board_alloc);
8
19
 
9
- rb_define_private_method(reversi_board, "board_initialize", board_initialize, 0);
20
+ /* The getter method for a Reversi::Board object. */
10
21
  rb_define_method(reversi_board, "columns", board_columns_getter, 0);
11
22
  rb_define_method(reversi_board, "stack", board_stack_getter, 0);
23
+
24
+ /* The instance method for a Reversi::Board object. */
12
25
  rb_define_method(reversi_board, "undo!", board_undo, 0);
13
26
 
27
+ /* These private methods are used in the board.rb file. */
28
+ rb_define_private_method(reversi_board, "board_initialize", board_initialize, 0);
14
29
  rb_define_private_method(reversi_board, "board_push_stack", board_push_stack, 1);
15
30
  rb_define_private_method(reversi_board, "board_status", board_status, 0);
16
31
  rb_define_private_method(reversi_board, "board_openness", board_openness, 2);
@@ -21,6 +36,11 @@ void Init_reversi(void) {
21
36
  rb_define_private_method(reversi_board, "board_flip_disks", board_flip_disks, 3);
22
37
  }
23
38
 
39
+ static VALUE board_alloc(VALUE class) {
40
+ struct board *ptr = ALLOC(struct board);
41
+ return Data_Wrap_Struct(class, 0, -1, ptr);
42
+ }
43
+
24
44
  static VALUE board_initialize(VALUE self) {
25
45
  int x, y;
26
46
  struct board *ptr;
@@ -39,6 +59,11 @@ static VALUE board_initialize(VALUE self) {
39
59
  return Qnil;
40
60
  }
41
61
 
62
+ /*
63
+ * The getter method for the instance variable `columns`.
64
+ *
65
+ * @return [Array]
66
+ */
42
67
  static VALUE board_columns_getter(VALUE self) {
43
68
  VALUE column = rb_ary_new();
44
69
  VALUE columns = rb_ary_new();
@@ -54,6 +79,11 @@ static VALUE board_columns_getter(VALUE self) {
54
79
  return columns;
55
80
  }
56
81
 
82
+ /*
83
+ * The getter method for the instance variable `stack`.
84
+ *
85
+ * @return [Array]
86
+ */
57
87
  static VALUE board_stack_getter(VALUE self) {
58
88
  VALUE stack = rb_ary_new();
59
89
  VALUE column = rb_ary_new();
@@ -73,6 +103,10 @@ static VALUE board_stack_getter(VALUE self) {
73
103
  return stack;
74
104
  }
75
105
 
106
+ /*
107
+ * Pops an array of the game board off of the stack,
108
+ * and that is stored in the instance variable `columns`.
109
+ */
76
110
  static VALUE board_undo(VALUE self) {
77
111
  struct board *ptr;
78
112
  Data_Get_Struct(self, struct board, ptr);
@@ -80,11 +114,22 @@ static VALUE board_undo(VALUE self) {
80
114
  return Qnil;
81
115
  }
82
116
 
117
+ /*
118
+ * Pushes an array of the game board onto a stack.
119
+ *
120
+ * @param limit [Integer] An upper limit size of the stack.
121
+ */
83
122
  static VALUE board_push_stack(VALUE self, VALUE limit) {
84
123
  push_stack(self, FIX2INT(limit));
85
124
  return Qnil;
86
125
  }
87
126
 
127
+ /*
128
+ * Returns an array containing the coordinates of each color.
129
+ * The arrays are stored `black`, `while`, and `none` in that order.
130
+ *
131
+ * @return [Array]
132
+ */
88
133
  static VALUE board_status(VALUE self) {
89
134
  VALUE black = rb_ary_new();
90
135
  VALUE white = rb_ary_new();
@@ -123,6 +168,13 @@ static VALUE board_status(VALUE self) {
123
168
  return status;
124
169
  }
125
170
 
171
+ /*
172
+ * Returns the openness of the coordinates.
173
+ *
174
+ * @param x [Integer] the column number
175
+ * @param y [Integer] the row number
176
+ * @return [Integer] the openness
177
+ */
126
178
  static VALUE board_openness(VALUE self, VALUE x, VALUE y) {
127
179
  int dx, dy, sum = 0;
128
180
  struct board *ptr;
@@ -137,12 +189,25 @@ static VALUE board_openness(VALUE self, VALUE x, VALUE y) {
137
189
  return INT2FIX(sum);
138
190
  }
139
191
 
192
+ /*
193
+ * Returns the disk color of supplied coordinates.
194
+ *
195
+ * @param x [Integer] the column number
196
+ * @param y [Integer] the row number
197
+ * @return [Integer] `black`: -1, `white`: 1, `none`: 0
198
+ */
140
199
  static VALUE board_at(VALUE self, VALUE x, VALUE y) {
141
200
  struct board *ptr;
142
201
  Data_Get_Struct(self, struct board, ptr);
143
202
  return INT2FIX(ptr->columns[FIX2INT(x)][FIX2INT(y)]);
144
203
  }
145
204
 
205
+ /*
206
+ * Counts the number of the supplied color's disks.
207
+ *
208
+ * @param color [Integer] `black`: -1, `white`: 1, `none`: 0
209
+ * @return [Integer] the sum of the counted disks
210
+ */
146
211
  static VALUE board_count_disks(VALUE self, VALUE color) {
147
212
  int x, y, count = 0;
148
213
  struct board *ptr;
@@ -156,6 +221,12 @@ static VALUE board_count_disks(VALUE self, VALUE color) {
156
221
  return INT2FIX(count);
157
222
  }
158
223
 
224
+ /*
225
+ * Returns an array of the next moves.
226
+ *
227
+ * @param color [Integer] `black`: -1, `white`: 1, `none`: 0
228
+ * @return [Array] the next moves
229
+ */
159
230
  static VALUE board_next_moves(VALUE self, VALUE color) {
160
231
  int x, y;
161
232
  VALUE move = rb_ary_new();
@@ -174,6 +245,13 @@ static VALUE board_next_moves(VALUE self, VALUE color) {
174
245
  return moves;
175
246
  }
176
247
 
248
+ /*
249
+ * Places a supplied color's disk on specified position.
250
+ *
251
+ * @param x [Integer] the column number
252
+ * @param y [Integer] the row number
253
+ * @param color [Integer] `black`: -1, `white`: 1, `none`: 0
254
+ */
177
255
  static VALUE board_put_disk(VALUE self, VALUE x, VALUE y, VALUE color) {
178
256
  struct board *ptr;
179
257
  Data_Get_Struct(self, struct board, ptr);
@@ -182,6 +260,14 @@ static VALUE board_put_disk(VALUE self, VALUE x, VALUE y, VALUE color) {
182
260
  return Qnil;
183
261
  }
184
262
 
263
+ /*
264
+ * Flips the opponent's disks between a new disk and another disk of my color.
265
+ * The invalid move has no effect.
266
+ *
267
+ * @param x [Integer] the column number
268
+ * @param y [Integer] the row number
269
+ * @param color [Integer] `black`: -1, `white`: 1, `none`: 0
270
+ */
185
271
  static VALUE board_flip_disks(VALUE self, VALUE x, VALUE y, VALUE color) {
186
272
  int dx, dy;
187
273
  struct board *ptr;
@@ -201,6 +287,10 @@ static VALUE board_flip_disks(VALUE self, VALUE x, VALUE y, VALUE color) {
201
287
  return Qnil;
202
288
  }
203
289
 
290
+ /*
291
+ * Flips the opponent's disks on one of these straight lines
292
+ * between a new disk and another disk of my color.
293
+ */
204
294
  void flip_disk(VALUE self, int x, int y, int dx, int dy, int color){
205
295
  struct board *ptr;
206
296
  Data_Get_Struct(self, struct board, ptr);
@@ -214,6 +304,10 @@ void flip_disk(VALUE self, int x, int y, int dx, int dy, int color){
214
304
  return;
215
305
  }
216
306
 
307
+ /*
308
+ * Whether or not a player can place a new disk on specified position.
309
+ * Returns `1` if the move is valid.
310
+ */
217
311
  int can_put(VALUE self, int x, int y, int color){
218
312
  int dx, dy;
219
313
  struct board *ptr;
@@ -232,6 +326,9 @@ int can_put(VALUE self, int x, int y, int color){
232
326
  return 0;
233
327
  }
234
328
 
329
+ /*
330
+ * Whether or not a player can flip the opponent's disks.
331
+ */
235
332
  int can_flip(VALUE self, int x, int y, int dx, int dy, int color){
236
333
  struct board *ptr;
237
334
  Data_Get_Struct(self, struct board, ptr);
@@ -3,6 +3,7 @@
3
3
  #include <memory.h>
4
4
 
5
5
  void Init_board(void);
6
+
6
7
  static VALUE board_alloc(VALUE class);
7
8
  static VALUE board_initialize(VALUE self);
8
9
  static VALUE board_columns_getter(VALUE self);
@@ -26,18 +27,3 @@ void pop_stack(int ary[10][10]);
26
27
  int stack_size(void);
27
28
  void delete_old(void);
28
29
  void reset_stack(void);
29
-
30
- struct stack{
31
- int stack_columns[10][10];
32
- struct stack *next;
33
- };
34
- struct stack *head = NULL;
35
-
36
- struct board {
37
- int columns[10][10];
38
- };
39
-
40
- static VALUE board_alloc(VALUE class) {
41
- struct board *ptr = ALLOC(struct board);
42
- return Data_Wrap_Struct(class, 0, -1, ptr);
43
- }
data/lib/reversi/board.rb CHANGED
@@ -120,7 +120,7 @@ module Reversi
120
120
  end
121
121
 
122
122
  # Flips the opponent's disks between a new disk and another disk of my color.
123
- # the invalid move has no effect.
123
+ # The invalid move has no effect.
124
124
  #
125
125
  # @param x [Symbol, Integer] the column number
126
126
  # @param y [Integer] the row number
@@ -20,7 +20,7 @@ module Reversi
20
20
  :disk_w => 'w',
21
21
  :disk_color_b => 0,
22
22
  :disk_color_w => 0,
23
- :initial_position => {:black => [[:d, 5], [:e, 4]], :white => [[:d, 4], [:e, 5]]},
23
+ :initial_position => {:black => [[4, 5], [5, 4]], :white => [[4, 4], [5, 5]]},
24
24
  :progress => false,
25
25
  :stack_limit => 3
26
26
  }
@@ -3,6 +3,7 @@ module Reversi
3
3
  autoload :RandomAI, "reversi/player/random_ai"
4
4
  autoload :NegaMaxAI, "reversi/player/nega_max_ai"
5
5
  autoload :MinMaxAI, "reversi/player/min_max_ai"
6
+ autoload :AlphaBetaAI, "reversi/player/alpha_beta_ai"
6
7
  autoload :Human, "reversi/player/human"
7
8
  end
8
9
  end
@@ -0,0 +1,70 @@
1
+ module Reversi::Player
2
+ class AlphaBetaAI < BasePlayer
3
+
4
+ N = 10000.freeze
5
+
6
+ def initialize(_color, _board)
7
+ super
8
+
9
+ points = [
10
+ 100, -10, 0, -1, -1, 0, -10, 100,
11
+ -10, -30, -5, -5, -5, -5, -30, -10,
12
+ 0, -5, 0, -1, -1, 0, -5, 0,
13
+ -1, -5, -1, -1, -1, -1, -5, -1,
14
+ -1, -5, -1, -1, -1, -1, -5, -1,
15
+ 0, -5, 0, -1, -1, 0, -5, 0,
16
+ -10, -30, -5, -5, -5, -5, -30, -10,
17
+ 100, -10, 0, -1, -1, 0, -10, 100
18
+ ]
19
+ @evaluation_value =
20
+ Hash[(1..8).map{ |x| (1..8).map{ |y| [[x, y], points.shift] } }.flatten(1) ]
21
+ end
22
+
23
+ def move(board)
24
+ moves = next_moves.sort_by{ |v| v[:openness] }.map{ |v| v[:move] }
25
+ return if moves.empty?
26
+ alpha = -N; beta = N
27
+ next_move = moves.map do |move|
28
+ { :move => move, :point => evaluate(move, board, alpha, beta, 3, true) }
29
+ end.max_by{ |v| v[:point] }[:move]
30
+ put_disk(*next_move)
31
+ end
32
+
33
+ def evaluate(move, board, alpha, beta, depth, color)
34
+ put_disk(*move, color)
35
+ moves = next_moves(!color).sort_by{ |v| v[:openness] }.map{ |v| v[:move] }
36
+
37
+ if depth == 1
38
+ status[:mine].inject(0){ |sum, xy| sum + @evaluation_value[xy] }
39
+
40
+ elsif moves.empty?
41
+ case depth
42
+ when ->(n){ n.odd? } then alpha
43
+ when ->(n){ n.even? } then beta end
44
+
45
+ else
46
+ case depth
47
+ when ->(n){ n.odd? }
48
+ beta = N
49
+ moves.each do |move|
50
+ val = evaluate(move, board, alpha, beta, depth - 1, !color)
51
+ beta = val if val < beta
52
+ return alpha if alpha > beta
53
+ end
54
+ beta
55
+ when ->(n){ n.even? }
56
+ alpha = -N
57
+ moves.each do |move|
58
+ val = evaluate(move, board, alpha, beta, depth - 1, !color)
59
+ alpha = val if val > alpha
60
+ return beta if alpha > beta
61
+ end
62
+ alpha
63
+ end
64
+ end
65
+
66
+ ensure
67
+ board.undo!
68
+ end
69
+ end
70
+ end
@@ -4,7 +4,7 @@ module Reversi::Player
4
4
  def initialize(_color, _board)
5
5
  super
6
6
 
7
- point = [
7
+ points = [
8
8
  100, -10, 0, -1, -1, 0, -10, 100,
9
9
  -10, -30, -5, -5, -5, -5, -30, -10,
10
10
  0, -5, 0, -1, -1, 0, -5, 0,
@@ -15,17 +15,15 @@ module Reversi::Player
15
15
  100, -10, 0, -1, -1, 0, -10, 100
16
16
  ]
17
17
  @evaluation_value =
18
- Hash[(1..8).map{ |x| (1..8).map{ |y| [[x, y], point.shift] } }.flatten(1) ]
18
+ Hash[(1..8).map{ |x| (1..8).map{ |y| [[x, y], points.shift] } }.flatten(1) ]
19
19
  end
20
20
 
21
21
  def move(board)
22
22
  moves = next_moves.map{ |v| v[:move] }
23
23
  return if moves.empty?
24
-
25
24
  next_move = moves.map do |move|
26
- { :move => move, :point => evaluate(move, board, 1, true) }
27
- end
28
- .max_by{ |v| v[:point] }[:move]
25
+ { :move => move, :point => evaluate(move, board, 3, true) }
26
+ end.max_by{ |v| v[:point] }[:move]
29
27
  put_disk(*next_move)
30
28
  end
31
29
 
@@ -33,12 +31,13 @@ module Reversi::Player
33
31
  put_disk(*move, color)
34
32
  moves = next_moves(!color).map{ |v| v[:move] }
35
33
 
36
- if depth == 3
34
+ if depth == 1
37
35
  status[:mine].inject(0){ |sum, xy| sum + @evaluation_value[xy] }
38
36
  elsif moves.empty?
39
37
  -100
38
+
40
39
  else
41
- values = moves.map{ |move| evaluate(move, board, depth + 1, !color) }
40
+ values = moves.map{ |move| evaluate(move, board, depth - 1, !color) }
42
41
  case depth
43
42
  when ->(n){ n.odd? } then values.min
44
43
  when ->(n){ n.even? } then values.max end
@@ -4,7 +4,7 @@ module Reversi::Player
4
4
  def initialize(_color, _board)
5
5
  super
6
6
 
7
- point = [
7
+ points = [
8
8
  100, -10, 0, -1, -1, 0, -10, 100,
9
9
  -10, -30, -5, -5, -5, -5, -30, -10,
10
10
  0, -5, 0, -1, -1, 0, -5, 0,
@@ -15,17 +15,15 @@ module Reversi::Player
15
15
  100, -10, 0, -1, -1, 0, -10, 100
16
16
  ]
17
17
  @evaluation_value =
18
- Hash[(1..8).map{ |x| (1..8).map{ |y| [[x, y], point.shift] } }.flatten(1) ]
18
+ Hash[(1..8).map{ |x| (1..8).map{ |y| [[x, y], points.shift] } }.flatten(1) ]
19
19
  end
20
20
 
21
21
  def move(board)
22
22
  moves = next_moves.map{ |v| v[:move] }
23
23
  return if moves.empty?
24
-
25
24
  next_move = moves.map do |move|
26
- { :move => move, :point => evaluate(move, board, 1, true) }
27
- end
28
- .max_by{ |v| v[:point] }[:move]
25
+ { :move => move, :point => evaluate(move, board, 3, true) }
26
+ end.max_by{ |v| v[:point] }[:move]
29
27
  put_disk(*next_move)
30
28
  end
31
29
 
@@ -33,12 +31,12 @@ module Reversi::Player
33
31
  put_disk(*move, color)
34
32
  moves = next_moves(!color).map{ |v| v[:move] }
35
33
 
36
- if depth == 3
34
+ if depth == 1
37
35
  status[:mine].inject(0){ |sum, xy| sum + @evaluation_value[xy] }
38
36
  elsif moves.empty?
39
37
  -100
40
38
  else
41
- -( moves.map{ |move| evaluate(move, board, depth + 1, !color) }.max )
39
+ -( moves.map{ |move| evaluate(move, board, depth - 1, !color) }.max )
42
40
  end
43
41
 
44
42
  ensure
@@ -1,3 +1,3 @@
1
1
  module Reversi
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reversi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - seinosuke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-11 00:00:00.000000000 Z
11
+ date: 2015-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -50,6 +50,7 @@ files:
50
50
  - lib/reversi/configuration.rb
51
51
  - lib/reversi/game.rb
52
52
  - lib/reversi/player.rb
53
+ - lib/reversi/player/alpha_beta_ai.rb
53
54
  - lib/reversi/player/base_player.rb
54
55
  - lib/reversi/player/human.rb
55
56
  - lib/reversi/player/min_max_ai.rb