reversi 0.2.0 → 1.0.0

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: 651aae750b3b767bc9375470adff0bb5414f0663
4
- data.tar.gz: b90881770c721b08e945d7f20b3433bf97437115
3
+ metadata.gz: 1ff1bf1812bca5e760682bda5b45a12ccdba645f
4
+ data.tar.gz: b8d577cc947632a87cc90baf852825f5c65d2a07
5
5
  SHA512:
6
- metadata.gz: 85398b003393d63e49e37bbdf9e59958d2e3cdf49d9d787b4bd95dfd1261d2498b7b1f217a21909ddd283ab59f12893d5f909294dda5887bf5d5ba375ec5067e
7
- data.tar.gz: 81821d25c301e6e18a0bda8088a730558ec96a00e0317eb104e03fbd83f2de2b8b4601d7bd5a0629c254d52c583b493cc21b8b57bca6f36c916b8a5a8056952c
6
+ metadata.gz: 06780bd5ce1eaa0581e80f60356de0f0ddf66d41c49e5a48789e84141a2f6d231e55b4f5f415ff737ea9673eef87bf9c449eabec663ac0b5e466025c1dd265a6
7
+ data.tar.gz: e7fa1a96392164b0359ad673334cddc5b9e4a8b19c0b98e44988da387c423e0a1adc18cf43410dc340e107e5dbfa6330aaa9a667a850825e7ea4702474a93844
data/Gemfile CHANGED
@@ -2,6 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'rake'
4
4
  gem 'yard'
5
+ gem 'rake-compiler'
5
6
 
6
7
  group :development do
7
8
  gem 'pry'
data/Rakefile CHANGED
@@ -8,3 +8,7 @@ YARD::Rake::YardocTask.new do |t|
8
8
  t.files = ['lib/**/*.rb', 'lib/*.rb']
9
9
  end
10
10
 
11
+ require "rake/extensiontask"
12
+ Rake::ExtensionTask.new "reversi" do |ext|
13
+ ext.lib_dir = "lib/reversi"
14
+ end
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('reversi/reversi')
@@ -0,0 +1,299 @@
1
+ #include "reversi.h"
2
+
3
+ void Init_reversi(void) {
4
+ VALUE reversi = rb_define_module("Reversi");
5
+ VALUE reversi_board = rb_define_class_under(reversi, "Board", rb_cObject);
6
+
7
+ rb_define_alloc_func(reversi_board, board_alloc);
8
+
9
+ rb_define_private_method(reversi_board, "board_initialize", board_initialize, 0);
10
+ rb_define_method(reversi_board, "columns", board_columns_getter, 0);
11
+ rb_define_method(reversi_board, "stack", board_stack_getter, 0);
12
+ rb_define_method(reversi_board, "undo!", board_undo, 0);
13
+
14
+ rb_define_private_method(reversi_board, "board_push_stack", board_push_stack, 1);
15
+ rb_define_private_method(reversi_board, "board_status", board_status, 0);
16
+ rb_define_private_method(reversi_board, "board_openness", board_openness, 2);
17
+ rb_define_private_method(reversi_board, "board_at", board_at, 2);
18
+ rb_define_private_method(reversi_board, "board_count_disks", board_count_disks, 1);
19
+ rb_define_private_method(reversi_board, "board_next_moves", board_next_moves, 1);
20
+ rb_define_private_method(reversi_board, "board_put_disk", board_put_disk, 3);
21
+ rb_define_private_method(reversi_board, "board_flip_disks", board_flip_disks, 3);
22
+ }
23
+
24
+ static VALUE board_initialize(VALUE self) {
25
+ int x, y;
26
+ struct board *ptr;
27
+ Data_Get_Struct(self, struct board, ptr);
28
+
29
+ reset_stack();
30
+ head = NULL;
31
+
32
+ for(x = 0; x < 10; x++) {
33
+ for(y = 0; y < 10; y++) {
34
+ if(x == 0 || x == 9) ptr->columns[x][y] = 2;
35
+ else if(y == 0 || y == 9) ptr->columns[x][y] = 2;
36
+ else ptr->columns[x][y] = 0;
37
+ }
38
+ }
39
+ return Qnil;
40
+ }
41
+
42
+ static VALUE board_columns_getter(VALUE self) {
43
+ VALUE column = rb_ary_new();
44
+ VALUE columns = rb_ary_new();
45
+ int x, y;
46
+ struct board *ptr;
47
+ Data_Get_Struct(self, struct board, ptr);
48
+
49
+ for(x = 0; x < 10; x++) {
50
+ column = rb_ary_new();
51
+ for(y = 0; y < 10; y++) rb_ary_push(column, INT2FIX(ptr->columns[x][y]));
52
+ rb_ary_push(columns, column);
53
+ }
54
+ return columns;
55
+ }
56
+
57
+ static VALUE board_stack_getter(VALUE self) {
58
+ VALUE stack = rb_ary_new();
59
+ VALUE column = rb_ary_new();
60
+ VALUE columns = rb_ary_new();
61
+ int x, y;
62
+ struct stack *sp;
63
+
64
+ for(sp = head; sp != NULL; sp = sp->next) {
65
+ columns = rb_ary_new();
66
+ for(x = 0; x < 10; x++) {
67
+ column = rb_ary_new();
68
+ for(y = 0; y < 10; y++) rb_ary_push(column, INT2FIX(sp->stack_columns[x][y]));
69
+ rb_ary_push(columns, column);
70
+ }
71
+ rb_ary_push(stack, columns);
72
+ }
73
+ return stack;
74
+ }
75
+
76
+ static VALUE board_undo(VALUE self) {
77
+ struct board *ptr;
78
+ Data_Get_Struct(self, struct board, ptr);
79
+ pop_stack(ptr->columns);
80
+ return Qnil;
81
+ }
82
+
83
+ static VALUE board_push_stack(VALUE self, VALUE limit) {
84
+ push_stack(self, FIX2INT(limit));
85
+ return Qnil;
86
+ }
87
+
88
+ static VALUE board_status(VALUE self) {
89
+ VALUE black = rb_ary_new();
90
+ VALUE white = rb_ary_new();
91
+ VALUE none = rb_ary_new();
92
+ VALUE position = rb_ary_new();
93
+ VALUE status = rb_ary_new();
94
+ int x, y;
95
+ struct board *ptr;
96
+ Data_Get_Struct(self, struct board, ptr);
97
+
98
+ for(x = 0; x < 10; x++) {
99
+ for(y = 0; y < 10; y++) {
100
+ switch (ptr->columns[x][y]) {
101
+ case -1:
102
+ rb_ary_push(position, INT2FIX(x));
103
+ rb_ary_push(position, INT2FIX(y));
104
+ rb_ary_push(black, position);
105
+ position = rb_ary_new(); break;
106
+ case 1:
107
+ rb_ary_push(position, INT2FIX(x));
108
+ rb_ary_push(position, INT2FIX(y));
109
+ rb_ary_push(white, position);
110
+ position = rb_ary_new(); break;
111
+ case 0:
112
+ rb_ary_push(position, INT2FIX(x));
113
+ rb_ary_push(position, INT2FIX(y));
114
+ rb_ary_push(none, position);
115
+ position = rb_ary_new(); break;
116
+ }
117
+ }
118
+ }
119
+
120
+ rb_ary_push(status, black);
121
+ rb_ary_push(status, white);
122
+ rb_ary_push(status, none);
123
+ return status;
124
+ }
125
+
126
+ static VALUE board_openness(VALUE self, VALUE x, VALUE y) {
127
+ int dx, dy, sum = 0;
128
+ struct board *ptr;
129
+ Data_Get_Struct(self, struct board, ptr);
130
+
131
+ for(dx = -1; dx < 2; dx++){
132
+ for(dy = -1; dy < 2; dy++){
133
+ if (dx == 0 && dy == 0) continue;
134
+ if (ptr->columns[FIX2INT(x) + dx][FIX2INT(y) + dy] == 0) sum += 1;
135
+ }
136
+ }
137
+ return INT2FIX(sum);
138
+ }
139
+
140
+ static VALUE board_at(VALUE self, VALUE x, VALUE y) {
141
+ struct board *ptr;
142
+ Data_Get_Struct(self, struct board, ptr);
143
+ return INT2FIX(ptr->columns[FIX2INT(x)][FIX2INT(y)]);
144
+ }
145
+
146
+ static VALUE board_count_disks(VALUE self, VALUE color) {
147
+ int x, y, count = 0;
148
+ struct board *ptr;
149
+ Data_Get_Struct(self, struct board, ptr);
150
+
151
+ for(x = 1; x < 9; x++){
152
+ for(y = 1; y < 9; y++){
153
+ if (ptr->columns[x][y] == FIX2INT(color)) count += 1;
154
+ }
155
+ }
156
+ return INT2FIX(count);
157
+ }
158
+
159
+ static VALUE board_next_moves(VALUE self, VALUE color) {
160
+ int x, y;
161
+ VALUE move = rb_ary_new();
162
+ VALUE moves = rb_ary_new();
163
+
164
+ for(x = 1; x < 9; x++){
165
+ for(y = 1; y < 9; y++){
166
+ if (can_put(self, x, y, FIX2INT(color)) == 1){
167
+ move = rb_ary_new();
168
+ rb_ary_push(move, INT2FIX(x));
169
+ rb_ary_push(move, INT2FIX(y));
170
+ rb_ary_push(moves, move);
171
+ }
172
+ }
173
+ }
174
+ return moves;
175
+ }
176
+
177
+ static VALUE board_put_disk(VALUE self, VALUE x, VALUE y, VALUE color) {
178
+ struct board *ptr;
179
+ Data_Get_Struct(self, struct board, ptr);
180
+
181
+ ptr->columns[FIX2INT(x)][FIX2INT(y)] = FIX2INT(color);
182
+ return Qnil;
183
+ }
184
+
185
+ static VALUE board_flip_disks(VALUE self, VALUE x, VALUE y, VALUE color) {
186
+ int dx, dy;
187
+ struct board *ptr;
188
+ Data_Get_Struct(self, struct board, ptr);
189
+ x = FIX2INT(x);
190
+ y = FIX2INT(y);
191
+ color = FIX2INT(color);
192
+
193
+ for(dx = -1; dx < 2; dx++){
194
+ for(dy = -1; dy < 2; dy++){
195
+ if (dx == 0 && dy == 0) continue;
196
+ if (ptr->columns[x + dx][y + dy] == (signed)(-color) &&
197
+ can_flip(self, x, y, dx, dy, color) == 1)
198
+ flip_disk(self, x, y, dx, dy, color);
199
+ }
200
+ }
201
+ return Qnil;
202
+ }
203
+
204
+ void flip_disk(VALUE self, int x, int y, int dx, int dy, int color){
205
+ struct board *ptr;
206
+ Data_Get_Struct(self, struct board, ptr);
207
+
208
+ x += dx; y += dy;
209
+ if (ptr->columns[x][y] == 2 ||
210
+ ptr->columns[x][y] == 0 ||
211
+ ptr->columns[x][y] == color) return;
212
+ ptr->columns[x][y] = color;
213
+ flip_disk(self, x, y, dx, dy, color);
214
+ return;
215
+ }
216
+
217
+ int can_put(VALUE self, int x, int y, int color){
218
+ int dx, dy;
219
+ struct board *ptr;
220
+ Data_Get_Struct(self, struct board, ptr);
221
+
222
+ if (ptr->columns[x][y] != 0) return 0;
223
+
224
+ for(dx = -1; dx < 2; dx++){
225
+ for(dy = -1; dy < 2; dy++){
226
+ if (dx == 0 && dy == 0) continue;
227
+ if (ptr->columns[x + dx][y + dy] == -color){
228
+ if (can_flip(self, x, y, dx, dy, color) == 1) return 1;
229
+ }
230
+ }
231
+ }
232
+ return 0;
233
+ }
234
+
235
+ int can_flip(VALUE self, int x, int y, int dx, int dy, int color){
236
+ struct board *ptr;
237
+ Data_Get_Struct(self, struct board, ptr);
238
+
239
+ while(1){
240
+ x += dx; y += dy;
241
+ if (ptr->columns[x][y] == color) return 1;
242
+ if (ptr->columns[x][y] == 2 || ptr->columns[x][y] == 0) break;
243
+ }
244
+ return 0;
245
+ }
246
+
247
+ void push_stack(VALUE self, int limit){
248
+ int size = 0;
249
+ struct board *bp;
250
+ struct stack *sp;
251
+ Data_Get_Struct(self, struct board, bp);
252
+
253
+ for(sp = head; sp != NULL; sp = sp->next);
254
+ sp = (struct stack *)malloc(sizeof(struct stack));
255
+
256
+ memcpy(sp->stack_columns, bp->columns, sizeof(bp->columns));
257
+ sp->next = head;
258
+ head = sp;
259
+
260
+ size = stack_size();
261
+ if (size > limit) delete_old();
262
+ return;
263
+ }
264
+
265
+ void pop_stack(int ary[10][10]){
266
+ struct stack *p;
267
+ memcpy(ary, head->stack_columns, sizeof(head->stack_columns));
268
+ p = head;
269
+ head = p->next;
270
+ free(p);
271
+ return;
272
+ }
273
+
274
+ int stack_size(void){
275
+ int count = 0;
276
+ struct stack *p;
277
+ for(p = head; p != NULL; p = p->next) count++;
278
+ return count;
279
+ }
280
+
281
+ void delete_old(void){
282
+ struct stack *p;
283
+ for(p = head; p->next->next != NULL; p = p->next);
284
+ p->next = NULL;
285
+ free(p->next);
286
+ return;
287
+ }
288
+
289
+ void reset_stack(void){
290
+ struct stack *p = head;
291
+ struct stack *tmp;
292
+
293
+ while(p != NULL){
294
+ tmp = p->next;
295
+ free(p);
296
+ p = tmp;
297
+ }
298
+ return;
299
+ }
@@ -0,0 +1,43 @@
1
+ #include <ruby.h>
2
+ #include <stdlib.h>
3
+ #include <memory.h>
4
+
5
+ void Init_board(void);
6
+ static VALUE board_alloc(VALUE class);
7
+ static VALUE board_initialize(VALUE self);
8
+ static VALUE board_columns_getter(VALUE self);
9
+ static VALUE board_stack_getter(VALUE self);
10
+ static VALUE board_push_stack(VALUE self, VALUE limit);
11
+ static VALUE board_undo(VALUE self);
12
+ static VALUE board_status(VALUE self);
13
+ static VALUE board_openness(VALUE self, VALUE x, VALUE y);
14
+ static VALUE board_at(VALUE self, VALUE x, VALUE y);
15
+ static VALUE board_count_disks(VALUE self, VALUE color);
16
+ static VALUE board_next_moves(VALUE self, VALUE color);
17
+ static VALUE board_put_disk(VALUE self, VALUE x, VALUE y, VALUE color);
18
+ static VALUE board_flip_disks(VALUE self, VALUE x, VALUE y, VALUE color);
19
+
20
+ void flip_disk(VALUE self, int x, int y, int dx, int dy, int color);
21
+ int can_put(VALUE self, int x, int y, int color);
22
+ int can_flip(VALUE self, int x, int y, int dx, int dy, int color);
23
+
24
+ void push_stack(VALUE self, int limit);
25
+ void pop_stack(int ary[10][10]);
26
+ int stack_size(void);
27
+ void delete_old(void);
28
+ 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
@@ -1,8 +1,6 @@
1
1
  module Reversi
2
2
  class Board
3
- attr_reader :options, :columns, :stack
4
-
5
- COORDINATES = (:a..:h).map{ |x| (1..8).map{ |y| [x, y] } }.flatten(1).freeze
3
+ attr_reader :options
6
4
 
7
5
  DISK = {
8
6
  :none => 0,
@@ -30,21 +28,15 @@ module Reversi
30
28
  # @return [Reversi::Board]
31
29
  def initialize(options = {})
32
30
  @options = options
33
- @stack = []
34
31
  [:disk_color_b, :disk_color_w].each do |color|
35
32
  if @options[color].is_a?(Symbol) || @options[color].is_a?(String)
36
33
  @options[color] = DISK_COLOR[@options[color].to_sym].to_i
37
34
  end
38
35
  end
39
- @columns = (0..9).map{ (0..9).map{ |_| DISK[:none] } }
36
+ board_initialize
40
37
  @options[:initial_position].each do |color, positions|
41
38
  positions.each{ |position| put_disk(*position, color) }
42
39
  end
43
- @columns.each do |col|
44
- col[0] = 2; col[-1] = 2
45
- end.tap do |cols|
46
- cols[0].fill(2); cols[-1].fill(2)
47
- end
48
40
  end
49
41
 
50
42
  # Returns a string of the game board in human-readable form.
@@ -53,7 +45,7 @@ module Reversi
53
45
  def to_s
54
46
  " #{[*'a'..'h'].join(" ")}\n" <<
55
47
  " #{"+---"*8}+\n" <<
56
- @columns[1][1..-2].zip(*@columns[2..8].map{ |col| col[1..-2] })
48
+ columns[1][1..-2].zip(*columns[2..8].map{ |col| col[1..-2] })
57
49
  .map{ |row| row.map do |e|
58
50
  case e
59
51
  when 0 then " "
@@ -70,26 +62,15 @@ module Reversi
70
62
  # Pushes an array of the game board onto a stack.
71
63
  # The stack size limit is 3(default).
72
64
  def push_stack
73
- x = [*:a..:h].index(x) + 1 if x.is_a? Symbol
74
- @stack.push(Marshal.load(Marshal.dump(@columns)))
75
- @stack.shift if @stack.size > @options[:stack_limit]
76
- end
77
-
78
- # Pops an array of the game board off of the stack,
79
- # and that is stored in the instance variable.(`@columns`)
80
- #
81
- # @param num [Integer] Be popped from the stack by the supplied number of times.
82
- def undo!(num = 1)
83
- num.times{ @columns = @stack.pop }
65
+ board_push_stack(@options[:stack_limit])
84
66
  end
85
67
 
86
68
  # Returns a hash containing the coordinates of each color.
87
69
  #
88
70
  # @return [Hash{Symbol => Array<Symbol, Integer>}]
89
71
  def status
90
- Hash[*[:none, :black, :white].map do |key|
91
- [key, COORDINATES.map{ |x, y| [x, y] if key == at(x, y) }.compact]
92
- end.flatten(1)]
72
+ ary = board_status
73
+ {:black => ary[0], :white => ary[1], :none => ary[2]}
93
74
  end
94
75
 
95
76
  # Returns the openness of the coordinates.
@@ -99,9 +80,7 @@ module Reversi
99
80
  # @return [Integer] the openness
100
81
  def openness(x, y)
101
82
  x = [*:a..:h].index(x) + 1 if x.is_a? Symbol
102
- ([-1,0,1].product([-1,0,1]) - [[0, 0]]).inject(0) do |sum, (dx, dy)|
103
- sum + (@columns[x + dx][y + dy] == 0 ? 1 : 0)
104
- end
83
+ board_openness(x, y)
105
84
  end
106
85
 
107
86
  # Returns the color of supplied coordinates.
@@ -111,7 +90,7 @@ module Reversi
111
90
  # @return [Symbol] the color or `:none`
112
91
  def at(x, y)
113
92
  x = [*:a..:h].index(x) + 1 if x.is_a? Symbol
114
- DISK.key(@columns[x][y])
93
+ DISK.key(board_at(x, y))
115
94
  end
116
95
 
117
96
  # Counts the number of the supplied color's disks.
@@ -119,9 +98,7 @@ module Reversi
119
98
  # @param color [Symbol]
120
99
  # @return [Integer] the sum of the counted disks
121
100
  def count_disks(color)
122
- @columns.flatten.inject(0) do |sum, e|
123
- sum + (e == DISK[color] ? 1 : 0)
124
- end
101
+ board_count_disks(DISK[color])
125
102
  end
126
103
 
127
104
  # Returns an array of the next moves.
@@ -129,10 +106,7 @@ module Reversi
129
106
  # @param color [Symbol]
130
107
  # @return [Array<Array<Symbol, Integer>>]
131
108
  def next_moves(color)
132
- @columns[1..8].map{ |col| col[1..-2] }
133
- .flatten.each_with_index.inject([]) do |list, (_, i)|
134
- list << (puttable?(*COORDINATES[i], color) ? COORDINATES[i] : nil)
135
- end.compact
109
+ board_next_moves(DISK[color])
136
110
  end
137
111
 
138
112
  # Places a supplied color's disk on specified position.
@@ -142,7 +116,7 @@ module Reversi
142
116
  # @param color [Symbol]
143
117
  def put_disk(x, y, color)
144
118
  x = [*:a..:h].index(x) + 1 if x.is_a? Symbol
145
- @columns[x][y] = DISK[color.to_sym]
119
+ board_put_disk(x, y, DISK[color])
146
120
  end
147
121
 
148
122
  # Flips the opponent's disks between a new disk and another disk of my color.
@@ -153,64 +127,7 @@ module Reversi
153
127
  # @param color [Symbol]
154
128
  def flip_disks(x, y, color)
155
129
  x = [*:a..:h].index(x) + 1 if x.is_a? Symbol
156
- [-1,0,1].product([-1,0,1]).each do |dx, dy|
157
- next if dx == 0 && dy == 0
158
- if @columns[x + dx][y + dy] == DISK[color]*(-1)
159
- flip_disk(x, y, dx, dy, color) if flippable?(x, y, dx, dy, color)
160
- end
161
- end
162
- end
163
-
164
- private
165
-
166
- # Flips the opponent's disks on one of these straight lines
167
- # between a new disk and another disk of my color.
168
- #
169
- # @param x [Symbol, Integer] the column number
170
- # @param y [Integer] the row number
171
- # @param dx [Integer] a horizontal difference
172
- # @param dy [Integer] a verticaldistance
173
- # @param color [Symbol]
174
- def flip_disk(x, y, dx, dy, color)
175
- return if [DISK[:wall], DISK[:none], DISK[color]].include?(@columns[x+dx][y+dy])
176
- @columns[x+dx][y+dy] = DISK[color]
177
- flip_disk(x+dx, y+dy, dx, dy, color)
178
- end
179
-
180
- # Whether or not a player can place a new disk on specified position.
181
- # Returns true if the move is valid.
182
- #
183
- # @param x [Symbol, Integer] the column number
184
- # @param y [Integer] the row number
185
- # @param color [Symbol]
186
- # @return [Boolean]
187
- def puttable?(x, y, color)
188
- x = [*:a..:h].index(x) + 1 if x.is_a? Symbol
189
- return false if @columns[x][y] != 0
190
- [-1,0,1].product([-1,0,1]).each do |dx, dy|
191
- next if dx == 0 && dy == 0
192
- if @columns[x + dx][y + dy] == DISK[color]*(-1)
193
- return true if flippable?(x, y, dx, dy, color)
194
- end
195
- end
196
- false
197
- end
198
-
199
- # Whether or not a player can flip the opponent's disks.
200
- #
201
- # @param x [Symbol, Integer] the column number
202
- # @param y [Integer] the row number
203
- # @param dx [Integer] a horizontal difference
204
- # @param dy [Integer] a verticaldistance
205
- # @param color [Symbol]
206
- # @return [Boolean]
207
- def flippable?(x, y, dx, dy, color)
208
- loop do
209
- x += dx; y += dy
210
- return true if @columns[x][y] == DISK[color]
211
- break if [DISK[:wall] ,DISK[:none]].include?(@columns[x][y])
212
- end
213
- false
130
+ board_flip_disks(x, y, DISK[color])
214
131
  end
215
132
  end
216
133
  end
@@ -18,7 +18,7 @@ module Reversi::Player
18
18
  @input_move = gets.chomp.split("")
19
19
  exit if [['q'], ['e','x','i','t']].include? @input_move
20
20
  redo if check_size == :redo
21
- @input_move[0] = @input_move[0].to_sym
21
+ @input_move[0] = [*:a..:h].index(@input_move[0].to_sym) + 1
22
22
  @input_move[1] = @input_move[1].to_i
23
23
  printf "\e[#{1}A"; STDOUT.flush
24
24
  print "#{" "*9}"
@@ -2,14 +2,14 @@ module Reversi::Player
2
2
  class NegamaxAI < BasePlayer
3
3
 
4
4
  POINT = {
5
- [:a, 1] => 100, [:b, 1] => -10, [:c, 1] => 0, [:d, 1] => -1, [:e, 1] => -1, [:f, 1] => 0, [:g, 1] => -10, [:h, 1] => 100,
6
- [:a, 2] => -10, [:b, 2] => -30, [:c, 2] => -5, [:d, 2] => -5, [:e, 2] => -5, [:f, 2] => -5, [:g, 2] => -30, [:h, 2] => -10,
7
- [:a, 3] => 0, [:b, 3] => -5, [:c, 3] => 0, [:d, 3] => -1, [:e, 3] => -1, [:f, 3] => 0, [:g, 3] => -5, [:h, 3] => 0,
8
- [:a, 4] => -1, [:b, 4] => -5, [:c, 4] => -1, [:d, 4] => -1, [:e, 4] => -1, [:f, 4] => -1, [:g, 4] => -5, [:h, 4] => -1,
9
- [:a, 5] => -1, [:b, 5] => -5, [:c, 5] => -1, [:d, 5] => -1, [:e, 5] => -1, [:f, 5] => -1, [:g, 5] => -5, [:h, 5] => -1,
10
- [:a, 6] => 0, [:b, 6] => -5, [:c, 6] => 0, [:d, 6] => -1, [:e, 6] => -1, [:f, 6] => 0, [:g, 6] => -5, [:h, 6] => 0,
11
- [:a, 7] => -10, [:b, 7] => -30, [:c, 7] => -5, [:d, 7] => -5, [:e, 7] => -5, [:f, 7] => -5, [:g, 7] => -30, [:h, 7] => -10,
12
- [:a, 8] => 100, [:b, 8] => -10, [:c, 8] => 0, [:d, 8] => -1, [:e, 8] => -1, [:f, 8] => 0, [:g, 8] => -12, [:h, 8] => 100
5
+ [1, 1] => 100, [2, 1] => -10, [3, 1] => 0, [4, 1] => -1, [5, 1] => -1, [6, 1] => 0, [7, 1] => -10, [8, 1] => 100,
6
+ [1, 2] => -10, [2, 2] => -30, [3, 2] => -5, [4, 2] => -5, [5, 2] => -5, [6, 2] => -5, [7, 2] => -30, [8, 2] => -10,
7
+ [1, 3] => 0, [2, 3] => -5, [3, 3] => 0, [4, 3] => -1, [5, 3] => -1, [6, 3] => 0, [7, 3] => -5, [8, 3] => 0,
8
+ [1, 4] => -1, [2, 4] => -5, [3, 4] => -1, [4, 4] => -1, [5, 4] => -1, [6, 4] => -1, [7, 4] => -5, [8, 4] => -1,
9
+ [1, 5] => -1, [2, 5] => -5, [3, 5] => -1, [4, 5] => -1, [5, 5] => -1, [6, 5] => -1, [7, 5] => -5, [8, 5] => -1,
10
+ [1, 6] => 0, [2, 6] => -5, [3, 6] => 0, [4, 6] => -1, [5, 6] => -1, [6, 6] => 0, [7, 6] => -5, [8, 6] => 0,
11
+ [1, 7] => -10, [2, 7] => -30, [3, 7] => -5, [4, 7] => -5, [5, 7] => -5, [6, 7] => -5, [7, 7] => -30, [8, 7] => -10,
12
+ [1, 8] => 100, [2, 8] => -10, [3, 8] => 0, [4, 8] => -1, [5, 8] => -1, [6, 8] => 0, [7, 8] => -12, [8, 8] => 100
13
13
  }.freeze
14
14
 
15
15
  def move(board)
@@ -1,3 +1,3 @@
1
1
  module Reversi
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/reversi.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "reversi/reversi"
1
2
  require "reversi/version"
2
3
  require "reversi/player"
3
4
  require "reversi/player/base_player"
data/reversi.gemspec CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
+ spec.extensions = ["ext/reversi/extconf.rb"]
20
21
 
21
22
  spec.add_development_dependency "bundler", "~> 1.7"
22
23
 
@@ -22,7 +22,7 @@ describe Reversi::Player::BasePlayer do
22
22
  describe "#next_moves" do
23
23
  context "when the first argument is omitted" do
24
24
  it do
25
- ans = [[:c, 4], [:d, 3], [:e, 6], [:f, 5]]
25
+ ans = [[3, 4], [4, 3], [5, 6], [6, 5]]
26
26
  expect(player.next_moves.map{ |move| move[:move] }).to eq ans
27
27
  end
28
28
 
@@ -30,13 +30,13 @@ describe Reversi::Player::BasePlayer do
30
30
  player.put_disk(:d, 3)
31
31
  player.put_disk(:e, 3, false)
32
32
  expect(player.next_moves[1][:openness]).to eq 8
33
- expect(player.next_moves[1][:result]).to eq [[:e, 3], [:e, 4]]
33
+ expect(player.next_moves[1][:result]).to eq [[5, 3], [5, 4]]
34
34
  end
35
35
  end
36
36
 
37
37
  context "when the first argument is `false`" do
38
38
  it do
39
- ans = [[:c, 5], [:d, 6], [:e, 3], [:f, 4]]
39
+ ans = [[3, 5], [4, 6], [5, 3], [6, 4]]
40
40
  expect(player.next_moves(false).map{ |move| move[:move] }).to eq ans
41
41
  end
42
42
 
@@ -44,7 +44,7 @@ describe Reversi::Player::BasePlayer do
44
44
  player.put_disk(:d, 3)
45
45
  player.put_disk(:e, 3, false)
46
46
  expect(player.next_moves(false)[0][:openness]).to eq 5
47
- expect(player.next_moves(false)[0][:result]).to eq [[:d, 3]]
47
+ expect(player.next_moves(false)[0][:result]).to eq [[4, 3]]
48
48
  end
49
49
  end
50
50
  end
@@ -66,7 +66,7 @@ describe Reversi::Player::BasePlayer do
66
66
  end
67
67
 
68
68
  describe "#status" do
69
- it { expect(player.status[:mine]).to eq [[:d, 5], [:e, 4]] }
70
- it { expect(player.status[:opponent]).to eq [[:d, 4], [:e, 5]] }
69
+ it { expect(player.status[:mine]).to eq [[4, 5], [5, 4]] }
70
+ it { expect(player.status[:opponent]).to eq [[4, 4], [5, 5]] }
71
71
  end
72
72
  end
data/spec/board_spec.rb CHANGED
@@ -91,13 +91,6 @@ describe Reversi::Board do
91
91
  expect{ board.undo! }.to change{ board.stack.size }.by(-1)
92
92
  end
93
93
  end
94
-
95
- context "when the first argument is supplied" do
96
- it "the number is used" do
97
- 3.times { board.push_stack }
98
- expect{ board.undo! 2 }.to change{ board.stack.size }.by(-2)
99
- end
100
- end
101
94
  end
102
95
 
103
96
  describe "#status" do
@@ -149,8 +142,8 @@ describe Reversi::Board do
149
142
  describe "#next_moves" do
150
143
  let(:disk_color_b) { 0 }
151
144
  let(:disk_color_w) { 0 }
152
- it { expect(board.next_moves(:black)).to eq [[:c, 4], [:d, 3], [:e, 6], [:f, 5]] }
153
- it { expect(board.next_moves(:white)).to eq [[:c, 5], [:d, 6], [:e, 3], [:f, 4]] }
145
+ it { expect(board.next_moves(:black)).to eq [[3, 4], [4, 3], [5, 6], [6, 5]] }
146
+ it { expect(board.next_moves(:white)).to eq [[3, 5], [4, 6], [5, 3], [6, 4]] }
154
147
  end
155
148
 
156
149
  describe "#put_disk, #flip_disks" do
data/spec/game_spec.rb CHANGED
@@ -14,7 +14,7 @@ describe Reversi::Game do
14
14
 
15
15
  context "before `player_w` places a piece on position [f4]" do
16
16
  it do
17
- ans = [[:c, 5], [:d, 6], [:e, 3], [:f, 4], [:g, 5], [:g, 7]]
17
+ ans = [[3, 5], [4, 6], [5, 3], [6, 4], [7, 5], [7, 7]]
18
18
  expect(@game.player_w.next_moves.map{ |move| move[:move] }).to eq ans
19
19
  end
20
20
  it { expect(@game.player_w.count_disks).to eq 3 }
@@ -26,7 +26,7 @@ describe Reversi::Game do
26
26
  @game.player_w.put_disk(:f, 4)
27
27
  end
28
28
  it do
29
- ans = [[:c, 5], [:c, 6], [:d, 6], [:f, 2], [:g, 2], [:h, 3]]
29
+ ans = [[3, 5], [3, 6], [4, 6], [6, 2], [7, 2], [8, 3]]
30
30
  expect(@game.player_w.next_moves.map{ |move| move[:move] }).to eq ans
31
31
  end
32
32
  it { expect(@game.player_w.count_disks).to eq 7 }
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: 0.2.0
4
+ version: 1.0.0
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-06 00:00:00.000000000 Z
11
+ date: 2015-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -29,7 +29,8 @@ description: |
29
29
  or easily make your original reversi game programs.
30
30
  email:
31
31
  executables: []
32
- extensions: []
32
+ extensions:
33
+ - ext/reversi/extconf.rb
33
34
  extra_rdoc_files: []
34
35
  files:
35
36
  - ".gitignore"
@@ -39,6 +40,9 @@ files:
39
40
  - LICENSE.txt
40
41
  - README.md
41
42
  - Rakefile
43
+ - ext/reversi/extconf.rb
44
+ - ext/reversi/reversi.c
45
+ - ext/reversi/reversi.h
42
46
  - images/reversi.gif
43
47
  - lib/reversi.rb
44
48
  - lib/reversi/board.rb