reversi 1.0.2 → 2.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: f21066f809daeaccbfdfbc19f61dc5ac79b0dbca
4
- data.tar.gz: dca98c6b7c7f64ae612e35dd3a218a9993b35434
3
+ metadata.gz: 0595624ced91db908b4f67fa83459a6f31e1f9ec
4
+ data.tar.gz: b32155cc37fa7816d0eceb7b2b97102934568ebc
5
5
  SHA512:
6
- metadata.gz: 0b6798e66984df642eb6fec17b0bf88a6d37d21c10b909558d6ca069a0fab63e347a76fc01106cf7993bf23f468c62da060a296341792b1058bedaa682d4eaee
7
- data.tar.gz: ae1a412572613d73f47b75aed52c63211f50b90d2a3a0f22d7a8d86a7b9dcf586553d25bf2792b708eb4215c864513c102febc43519eae4ce241c194fdd529e1
6
+ metadata.gz: 3eee7c4c79aad77ba5bcc665786498f7fc62c2fac0484d6c3537e52c7520a7dfc1072f5141aad1665f52e63b9a4fa5ed2211c4e06b6eda77dec948590ef78d4d
7
+ data.tar.gz: 535dcd06b6426edab71f8f74597e38a4ae84e24915a2a32b0377d281704bdadc1aac42b17a125165fd4b7dd0b8bdb46a0b922eb83988b6b1f4564bb7aa2d1f21
data/README.md CHANGED
@@ -83,20 +83,21 @@ game.start
83
83
 
84
84
  You can make your original player class by inheriting `Reversi::Player::BasePlayer` and defining `move` method.
85
85
 
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.
86
+ `next_moves` method returns an array of the next moves. 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.
87
87
 
88
88
  * **Example of Random Player**
89
89
 
90
90
  ```ruby
91
91
  class MyAI < Reversi::Player::BasePlayer
92
92
  def move(board)
93
- moves = next_moves.map{ |v| v[:move] }
93
+ moves = next_moves
94
94
  put_disk(*moves.sample) unless moves.empty?
95
95
  end
96
96
  end
97
97
 
98
98
  Reversi.configure do |config|
99
99
  config.player_b = MyAI
100
+ config.progress = true
100
101
  end
101
102
 
102
103
  game = Reversi::Game.new
@@ -127,7 +128,7 @@ class MyAI < Reversi::Player::BasePlayer
127
128
  end
128
129
 
129
130
  def move(board)
130
- moves = next_moves.map{ |v| v[:move] }
131
+ moves = next_moves
131
132
  return if moves.empty?
132
133
  next_move = moves.map do |move|
133
134
  { :move => move, :point => evaluate(move, board, 3, true) }
@@ -140,7 +141,7 @@ class MyAI < Reversi::Player::BasePlayer
140
141
  put_disk(*move, color)
141
142
 
142
143
  # Acquire the branches of this node.
143
- moves = next_moves(!color).map{ |v| v[:move] }
144
+ moves = next_moves(!color)
144
145
 
145
146
  # Evaluate a current game-state when a search reaches the leaf node.
146
147
  if depth == 1
@@ -167,6 +168,7 @@ end
167
168
 
168
169
  Reversi.configure do |config|
169
170
  config.player_b = MyAI
171
+ config.progress = true
170
172
  end
171
173
 
172
174
  game = Reversi::Game.new
data/black ADDED
File without changes
@@ -0,0 +1,226 @@
1
+ #include "bit_board_functions.h"
2
+
3
+ unsigned long XY2BB(int x, int y) {
4
+ return (unsigned long)1 << ((8-x) + (8-y) * 8);
5
+ }
6
+
7
+ VALUE BB2XY(unsigned long bb) {
8
+ VALUE xy = rb_ary_new();
9
+
10
+ switch(bb) {
11
+ case 0x8000000000000000: rb_ary_push(xy, INT2FIX(1)), rb_ary_push(xy, INT2FIX(1)); break;
12
+ case 0x4000000000000000: rb_ary_push(xy, INT2FIX(2)), rb_ary_push(xy, INT2FIX(1)); break;
13
+ case 0x2000000000000000: rb_ary_push(xy, INT2FIX(3)), rb_ary_push(xy, INT2FIX(1)); break;
14
+ case 0x1000000000000000: rb_ary_push(xy, INT2FIX(4)), rb_ary_push(xy, INT2FIX(1)); break;
15
+ case 0x0800000000000000: rb_ary_push(xy, INT2FIX(5)), rb_ary_push(xy, INT2FIX(1)); break;
16
+ case 0x0400000000000000: rb_ary_push(xy, INT2FIX(6)), rb_ary_push(xy, INT2FIX(1)); break;
17
+ case 0x0200000000000000: rb_ary_push(xy, INT2FIX(7)), rb_ary_push(xy, INT2FIX(1)); break;
18
+ case 0x0100000000000000: rb_ary_push(xy, INT2FIX(8)), rb_ary_push(xy, INT2FIX(1)); break;
19
+
20
+ case 0x0080000000000000: rb_ary_push(xy, INT2FIX(1)), rb_ary_push(xy, INT2FIX(2)); break;
21
+ case 0x0040000000000000: rb_ary_push(xy, INT2FIX(2)), rb_ary_push(xy, INT2FIX(2)); break;
22
+ case 0x0020000000000000: rb_ary_push(xy, INT2FIX(3)), rb_ary_push(xy, INT2FIX(2)); break;
23
+ case 0x0010000000000000: rb_ary_push(xy, INT2FIX(4)), rb_ary_push(xy, INT2FIX(2)); break;
24
+ case 0x0008000000000000: rb_ary_push(xy, INT2FIX(5)), rb_ary_push(xy, INT2FIX(2)); break;
25
+ case 0x0004000000000000: rb_ary_push(xy, INT2FIX(6)), rb_ary_push(xy, INT2FIX(2)); break;
26
+ case 0x0002000000000000: rb_ary_push(xy, INT2FIX(7)), rb_ary_push(xy, INT2FIX(2)); break;
27
+ case 0x0001000000000000: rb_ary_push(xy, INT2FIX(8)), rb_ary_push(xy, INT2FIX(2)); break;
28
+
29
+ case 0x0000800000000000: rb_ary_push(xy, INT2FIX(1)), rb_ary_push(xy, INT2FIX(3)); break;
30
+ case 0x0000400000000000: rb_ary_push(xy, INT2FIX(2)), rb_ary_push(xy, INT2FIX(3)); break;
31
+ case 0x0000200000000000: rb_ary_push(xy, INT2FIX(3)), rb_ary_push(xy, INT2FIX(3)); break;
32
+ case 0x0000100000000000: rb_ary_push(xy, INT2FIX(4)), rb_ary_push(xy, INT2FIX(3)); break;
33
+ case 0x0000080000000000: rb_ary_push(xy, INT2FIX(5)), rb_ary_push(xy, INT2FIX(3)); break;
34
+ case 0x0000040000000000: rb_ary_push(xy, INT2FIX(6)), rb_ary_push(xy, INT2FIX(3)); break;
35
+ case 0x0000020000000000: rb_ary_push(xy, INT2FIX(7)), rb_ary_push(xy, INT2FIX(3)); break;
36
+ case 0x0000010000000000: rb_ary_push(xy, INT2FIX(8)), rb_ary_push(xy, INT2FIX(3)); break;
37
+
38
+ case 0x0000008000000000: rb_ary_push(xy, INT2FIX(1)), rb_ary_push(xy, INT2FIX(4)); break;
39
+ case 0x0000004000000000: rb_ary_push(xy, INT2FIX(2)), rb_ary_push(xy, INT2FIX(4)); break;
40
+ case 0x0000002000000000: rb_ary_push(xy, INT2FIX(3)), rb_ary_push(xy, INT2FIX(4)); break;
41
+ case 0x0000001000000000: rb_ary_push(xy, INT2FIX(4)), rb_ary_push(xy, INT2FIX(4)); break;
42
+ case 0x0000000800000000: rb_ary_push(xy, INT2FIX(5)), rb_ary_push(xy, INT2FIX(4)); break;
43
+ case 0x0000000400000000: rb_ary_push(xy, INT2FIX(6)), rb_ary_push(xy, INT2FIX(4)); break;
44
+ case 0x0000000200000000: rb_ary_push(xy, INT2FIX(7)), rb_ary_push(xy, INT2FIX(4)); break;
45
+ case 0x0000000100000000: rb_ary_push(xy, INT2FIX(8)), rb_ary_push(xy, INT2FIX(4)); break;
46
+
47
+ case 0x0000000080000000: rb_ary_push(xy, INT2FIX(1)), rb_ary_push(xy, INT2FIX(5)); break;
48
+ case 0x0000000040000000: rb_ary_push(xy, INT2FIX(2)), rb_ary_push(xy, INT2FIX(5)); break;
49
+ case 0x0000000020000000: rb_ary_push(xy, INT2FIX(3)), rb_ary_push(xy, INT2FIX(5)); break;
50
+ case 0x0000000010000000: rb_ary_push(xy, INT2FIX(4)), rb_ary_push(xy, INT2FIX(5)); break;
51
+ case 0x0000000008000000: rb_ary_push(xy, INT2FIX(5)), rb_ary_push(xy, INT2FIX(5)); break;
52
+ case 0x0000000004000000: rb_ary_push(xy, INT2FIX(6)), rb_ary_push(xy, INT2FIX(5)); break;
53
+ case 0x0000000002000000: rb_ary_push(xy, INT2FIX(7)), rb_ary_push(xy, INT2FIX(5)); break;
54
+ case 0x0000000001000000: rb_ary_push(xy, INT2FIX(8)), rb_ary_push(xy, INT2FIX(5)); break;
55
+
56
+ case 0x0000000000800000: rb_ary_push(xy, INT2FIX(1)), rb_ary_push(xy, INT2FIX(6)); break;
57
+ case 0x0000000000400000: rb_ary_push(xy, INT2FIX(2)), rb_ary_push(xy, INT2FIX(6)); break;
58
+ case 0x0000000000200000: rb_ary_push(xy, INT2FIX(3)), rb_ary_push(xy, INT2FIX(6)); break;
59
+ case 0x0000000000100000: rb_ary_push(xy, INT2FIX(4)), rb_ary_push(xy, INT2FIX(6)); break;
60
+ case 0x0000000000080000: rb_ary_push(xy, INT2FIX(5)), rb_ary_push(xy, INT2FIX(6)); break;
61
+ case 0x0000000000040000: rb_ary_push(xy, INT2FIX(6)), rb_ary_push(xy, INT2FIX(6)); break;
62
+ case 0x0000000000020000: rb_ary_push(xy, INT2FIX(7)), rb_ary_push(xy, INT2FIX(6)); break;
63
+ case 0x0000000000010000: rb_ary_push(xy, INT2FIX(8)), rb_ary_push(xy, INT2FIX(6)); break;
64
+
65
+ case 0x0000000000008000: rb_ary_push(xy, INT2FIX(1)), rb_ary_push(xy, INT2FIX(7)); break;
66
+ case 0x0000000000004000: rb_ary_push(xy, INT2FIX(2)), rb_ary_push(xy, INT2FIX(7)); break;
67
+ case 0x0000000000002000: rb_ary_push(xy, INT2FIX(3)), rb_ary_push(xy, INT2FIX(7)); break;
68
+ case 0x0000000000001000: rb_ary_push(xy, INT2FIX(4)), rb_ary_push(xy, INT2FIX(7)); break;
69
+ case 0x0000000000000800: rb_ary_push(xy, INT2FIX(5)), rb_ary_push(xy, INT2FIX(7)); break;
70
+ case 0x0000000000000400: rb_ary_push(xy, INT2FIX(6)), rb_ary_push(xy, INT2FIX(7)); break;
71
+ case 0x0000000000000200: rb_ary_push(xy, INT2FIX(7)), rb_ary_push(xy, INT2FIX(7)); break;
72
+ case 0x0000000000000100: rb_ary_push(xy, INT2FIX(8)), rb_ary_push(xy, INT2FIX(7)); break;
73
+
74
+ case 0x0000000000000080: rb_ary_push(xy, INT2FIX(1)), rb_ary_push(xy, INT2FIX(8)); break;
75
+ case 0x0000000000000040: rb_ary_push(xy, INT2FIX(2)), rb_ary_push(xy, INT2FIX(8)); break;
76
+ case 0x0000000000000020: rb_ary_push(xy, INT2FIX(3)), rb_ary_push(xy, INT2FIX(8)); break;
77
+ case 0x0000000000000010: rb_ary_push(xy, INT2FIX(4)), rb_ary_push(xy, INT2FIX(8)); break;
78
+ case 0x0000000000000008: rb_ary_push(xy, INT2FIX(5)), rb_ary_push(xy, INT2FIX(8)); break;
79
+ case 0x0000000000000004: rb_ary_push(xy, INT2FIX(6)), rb_ary_push(xy, INT2FIX(8)); break;
80
+ case 0x0000000000000002: rb_ary_push(xy, INT2FIX(7)), rb_ary_push(xy, INT2FIX(8)); break;
81
+ case 0x0000000000000001: rb_ary_push(xy, INT2FIX(8)), rb_ary_push(xy, INT2FIX(8)); break;
82
+ }
83
+ return xy;
84
+ }
85
+
86
+ unsigned long rotate_r90(unsigned long bb) {
87
+ bb = ((bb << 8) & 0xAA00AA00AA00AA00) |
88
+ ((bb >> 8) & 0x0055005500550055) |
89
+ ((bb << 1) & 0x00AA00AA00AA00AA) |
90
+ ((bb >> 1) & 0x5500550055005500);
91
+ bb = ((bb << 16) & 0xCCCC0000CCCC0000) |
92
+ ((bb >> 16) & 0x0000333300003333) |
93
+ ((bb << 2) & 0x0000CCCC0000CCCC) |
94
+ ((bb >> 2) & 0x3333000033330000);
95
+ bb = ((bb << 32) & 0xF0F0F0F000000000) |
96
+ ((bb >> 32) & 0x000000000F0F0F0F) |
97
+ ((bb << 4) & 0x00000000F0F0F0F0) |
98
+ ((bb >> 4) & 0x0F0F0F0F00000000);
99
+ return bb;
100
+ }
101
+
102
+ unsigned long rotate_l90(unsigned long bb) {
103
+ bb = ((bb << 1) & 0xAA00AA00AA00AA00) |
104
+ ((bb >> 1) & 0x0055005500550055) |
105
+ ((bb >> 8) & 0x00AA00AA00AA00AA) |
106
+ ((bb << 8) & 0x5500550055005500);
107
+ bb = ((bb << 2) & 0xCCCC0000CCCC0000) |
108
+ ((bb >> 2) & 0x0000333300003333) |
109
+ ((bb >> 16) & 0x0000CCCC0000CCCC) |
110
+ ((bb << 16) & 0x3333000033330000);
111
+ bb = ((bb << 4) & 0xF0F0F0F000000000) |
112
+ ((bb >> 4) & 0x000000000F0F0F0F) |
113
+ ((bb >> 32) & 0x00000000F0F0F0F0) |
114
+ ((bb << 32) & 0x0F0F0F0F00000000);
115
+ return bb;
116
+ }
117
+
118
+ unsigned long rotate_r45(unsigned long bb) {
119
+ bb = (bb & 0x0101010101010101) |
120
+ (((bb << 8) | (bb >> 56)) & 0x0202020202020202) |
121
+ (((bb << 16) | (bb >> 48)) & 0x0404040404040404) |
122
+ (((bb << 24) | (bb >> 40)) & 0x0808080808080808) |
123
+ (((bb << 32) | (bb >> 32)) & 0x1010101010101010) |
124
+ (((bb << 40) | (bb >> 24)) & 0x2020202020202020) |
125
+ (((bb << 48) | (bb >> 16)) & 0x4040404040404040) |
126
+ (((bb << 56) | (bb >> 8)) & 0x8080808080808080);
127
+ return bb;
128
+ }
129
+
130
+ unsigned long rotate_l45(unsigned long bb) {
131
+ bb = (bb & 0x0101010101010101) |
132
+ (((bb >> 8) | (bb << 56)) & 0x0202020202020202) |
133
+ (((bb >> 16) | (bb << 48)) & 0x0404040404040404) |
134
+ (((bb >> 24) | (bb << 40)) & 0x0808080808080808) |
135
+ (((bb >> 32) | (bb << 32)) & 0x1010101010101010) |
136
+ (((bb >> 40) | (bb << 24)) & 0x2020202020202020) |
137
+ (((bb >> 48) | (bb << 16)) & 0x4040404040404040) |
138
+ (((bb >> 56) | (bb << 8)) & 0x8080808080808080);
139
+ return bb;
140
+ }
141
+
142
+ unsigned long horizontal_pat(unsigned long my, unsigned long op, unsigned long p) {
143
+ op &= 0x7E7E7E7E7E7E7E7E;
144
+ return right_pat(my, op, p) | left_pat(my, op, p);
145
+ }
146
+
147
+ unsigned long vertical_pat(unsigned long my, unsigned long op, unsigned long p) {
148
+ my = rotate_r90(my);
149
+ op = rotate_r90(op & 0x00FFFFFFFFFFFF00);
150
+ p = rotate_r90(p);
151
+ return rotate_l90(right_pat(my, op, p) | left_pat(my, op, p));
152
+ }
153
+
154
+ unsigned long diagonal_pat(unsigned long my, unsigned long op, unsigned long p) {
155
+ unsigned long my_r45 = rotate_r45(my);
156
+ unsigned long op_r45 = rotate_r45(op & 0x007E7E7E7E7E7E00);
157
+ unsigned long p_r45 = rotate_r45(p);
158
+ unsigned long my_l45 = rotate_l45(my);
159
+ unsigned long op_l45 = rotate_l45(op & 0x00FF7E7E7E7E7E00);
160
+ unsigned long p_l45 = rotate_l45(p);
161
+ return rotate_l45(right_pat(my_r45, op_r45, p_r45) | left_pat(my_r45, op_r45, p_r45)) |
162
+ rotate_r45(right_pat(my_l45, op_l45, p_l45) | left_pat(my_l45, op_l45, p_l45));
163
+ }
164
+
165
+ unsigned long right_pat(unsigned long my, unsigned long op, unsigned long p) {
166
+ unsigned long rev = (p >> 1) & op;
167
+ rev |= (rev >> 1) & op;
168
+ rev |= (rev >> 1) & op;
169
+ rev |= (rev >> 1) & op;
170
+ rev |= (rev >> 1) & op;
171
+ rev |= (rev >> 1) & op;
172
+ return ((rev >> 1) & my) == 0 ? 0 : rev;
173
+ }
174
+
175
+ unsigned long left_pat(unsigned long my, unsigned long op, unsigned long p) {
176
+ unsigned long rev = (p << 1) & op;
177
+ rev |= (rev << 1) & op;
178
+ rev |= (rev << 1) & op;
179
+ rev |= (rev << 1) & op;
180
+ rev |= (rev << 1) & op;
181
+ rev |= (rev << 1) & op;
182
+ return ((rev << 1) & my) == 0 ? 0 : rev;
183
+ }
184
+
185
+ unsigned long horizontal_pos(unsigned long my, unsigned long op, unsigned long blank) {
186
+ op &= 0x7E7E7E7E7E7E7E7E;
187
+ return right_pos(my, op, blank) | left_pos(my, op, blank);
188
+ }
189
+
190
+ unsigned long vertical_pos(unsigned long my, unsigned long op, unsigned long blank) {
191
+ my = rotate_r90(my);
192
+ op = rotate_r90(op & 0x00FFFFFFFFFFFF00);
193
+ blank = rotate_r90(blank);
194
+ return rotate_l90(right_pos(my, op, blank) | left_pos(my, op, blank));
195
+ }
196
+
197
+ unsigned long diagonal_pos(unsigned long my, unsigned long op, unsigned long blank) {
198
+ unsigned long my_r45 = rotate_r45(my);
199
+ unsigned long op_r45 = rotate_r45(op & 0x007E7E7E7E7E7E00);
200
+ unsigned long blank_r45 = rotate_r45(blank);
201
+ unsigned long my_l45 = rotate_l45(my);
202
+ unsigned long op_l45 = rotate_l45(op & 0x007E7E7E7E7E7E00);
203
+ unsigned long blank_l45 = rotate_l45(blank);
204
+ return rotate_l45(right_pos(my_r45, op_r45, blank_r45) | left_pos(my_r45, op_r45, blank_r45)) |
205
+ rotate_r45(right_pos(my_l45, op_l45, blank_l45) | left_pos(my_l45, op_l45, blank_l45));
206
+ }
207
+
208
+ unsigned long right_pos(unsigned long my, unsigned long op, unsigned long blank) {
209
+ unsigned long rev = (my << 1) & op;
210
+ rev |= (rev << 1) & op;
211
+ rev |= (rev << 1) & op;
212
+ rev |= (rev << 1) & op;
213
+ rev |= (rev << 1) & op;
214
+ rev |= (rev << 1) & op;
215
+ return (rev << 1) & blank;
216
+ }
217
+
218
+ unsigned long left_pos(unsigned long my, unsigned long op, unsigned long blank) {
219
+ unsigned long rev = (my >> 1) & op;
220
+ rev |= (rev >> 1) & op;
221
+ rev |= (rev >> 1) & op;
222
+ rev |= (rev >> 1) & op;
223
+ rev |= (rev >> 1) & op;
224
+ rev |= (rev >> 1) & op;
225
+ return (rev >> 1) & blank;
226
+ }
@@ -0,0 +1,26 @@
1
+ #ifndef BIT_BOARD_FUNCTIONS_H
2
+ #define BIT_BOARD_FUNCTIONS_H
3
+
4
+ #include "reversi.h"
5
+
6
+ unsigned long XY2BB(int x, int y);
7
+ VALUE BB2XY(unsigned long bb);
8
+
9
+ unsigned long rotate_r90(unsigned long bb);
10
+ unsigned long rotate_l90(unsigned long bb);
11
+ unsigned long rotate_r45(unsigned long bb);
12
+ unsigned long rotate_l45(unsigned long bb);
13
+
14
+ unsigned long horizontal_pat(unsigned long my, unsigned long op, unsigned long p);
15
+ unsigned long vertical_pat(unsigned long my, unsigned long op, unsigned long p);
16
+ unsigned long diagonal_pat(unsigned long my, unsigned long op, unsigned long p);
17
+ unsigned long right_pat(unsigned long my, unsigned long op, unsigned long p);
18
+ unsigned long left_pat(unsigned long my, unsigned long op, unsigned long p);
19
+
20
+ unsigned long horizontal_pos(unsigned long my, unsigned long op, unsigned long blank);
21
+ unsigned long vertical_pos(unsigned long my, unsigned long op, unsigned long blank);
22
+ unsigned long diagonal_pos(unsigned long my, unsigned long op, unsigned long blank);
23
+ unsigned long right_pos(unsigned long my, unsigned long op, unsigned long blank);
24
+ unsigned long left_pos(unsigned long my, unsigned long op, unsigned long blank);
25
+
26
+ #endif
@@ -0,0 +1,253 @@
1
+ #include "board.h"
2
+
3
+ VALUE bit_board_alloc(VALUE class) {
4
+ struct bit_board *ptr = ALLOC(struct bit_board);
5
+ return Data_Wrap_Struct(class, 0, -1, ptr);
6
+ }
7
+
8
+ /*
9
+ * This method is used in the `Reversi::Board.new` method.
10
+ */
11
+ VALUE board_initialize(VALUE self) {
12
+ struct bit_board *ptr;
13
+ Data_Get_Struct(self, struct bit_board, ptr);
14
+ ptr->black = 0x0000000000000000;
15
+ ptr->white = 0x0000000000000000;
16
+ return Qnil;
17
+ }
18
+
19
+ /*
20
+ * The setter method for `bit_board.black`.
21
+ *
22
+ * @param black [Fixnum, Bignum] a bitboard for black
23
+ */
24
+ VALUE black_setter(VALUE self, VALUE black) {
25
+ struct bit_board *ptr;
26
+ Data_Get_Struct(self, struct bit_board, ptr);
27
+ ptr->black = NUM2ULONG(black);
28
+ return Qnil;
29
+ }
30
+
31
+ /*
32
+ * The setter method for `bit_board.white`.
33
+ *
34
+ * @param black [Fixnum, Bignum] a bitboard for white
35
+ */
36
+ VALUE white_setter(VALUE self, VALUE white) {
37
+ struct bit_board *ptr;
38
+ Data_Get_Struct(self, struct bit_board, ptr);
39
+ ptr->white = NUM2ULONG(white);
40
+ return Qnil;
41
+ }
42
+
43
+ /*
44
+ * The getter method for `bit_board.black`.
45
+ *
46
+ * @return [Fixnum, Bignum]
47
+ */
48
+ VALUE black_getter(VALUE self) {
49
+ struct bit_board *ptr;
50
+ Data_Get_Struct(self, struct bit_board, ptr);
51
+ return ULONG2NUM(ptr->black);
52
+ }
53
+
54
+ /*
55
+ * The getter method for `bit_board.white`.
56
+ *
57
+ * @return [Fixnum, Bignum]
58
+ */
59
+ VALUE white_getter(VALUE self) {
60
+ struct bit_board *ptr;
61
+ Data_Get_Struct(self, struct bit_board, ptr);
62
+ return ULONG2NUM(ptr->white);
63
+ }
64
+
65
+ /*
66
+ * Returns a hash containing the coordinates of each color.
67
+ *
68
+ * @return [Hash{Symbol => Array<Array<Integer, Integer>>}]
69
+ */
70
+ VALUE status(VALUE self) {
71
+ VALUE black_ary = rb_ary_new();
72
+ VALUE white_ary = rb_ary_new();
73
+ VALUE none_ary = rb_ary_new();
74
+ VALUE status = rb_hash_new();
75
+ unsigned long black = 0, white = 0, blank = 0, p = 0;
76
+ struct bit_board *ptr;
77
+ Data_Get_Struct(self, struct bit_board, ptr);
78
+
79
+ black = ptr->black;
80
+ while (black != 0) {
81
+ p = black & (~black + 1);
82
+ rb_ary_push(black_ary, BB2XY(p));
83
+ black ^= p;
84
+ }
85
+ rb_hash_aset(status, ID2SYM(rb_intern("black")), black_ary);
86
+
87
+ white = ptr->white;
88
+ while (white != 0) {
89
+ p = white & (~white + 1);
90
+ rb_ary_push(white_ary, BB2XY(p));
91
+ white ^= p;
92
+ }
93
+ rb_hash_aset(status, ID2SYM(rb_intern("white")), white_ary);
94
+
95
+ blank = ~(ptr->black | ptr->white);
96
+ while (blank != 0) {
97
+ p = blank & (~blank + 1);
98
+ rb_ary_push(none_ary, BB2XY(p));
99
+ blank ^= p;
100
+ }
101
+ rb_hash_aset(status, ID2SYM(rb_intern("none")), none_ary);
102
+
103
+ return status;
104
+ }
105
+
106
+ /*
107
+ * Returns the openness of the coordinates.
108
+ *
109
+ * @param rb_x [Integer] the column number
110
+ * @param rb_y [Integer] the row number
111
+ * @return [Integer] the openness
112
+ */
113
+ VALUE openness(VALUE self, VALUE rb_x, VALUE rb_y) {
114
+ unsigned long p = XY2BB(FIX2INT(rb_x), FIX2INT(rb_y));
115
+ unsigned long blank = 0, bb = 0;
116
+ struct bit_board *ptr;
117
+ Data_Get_Struct(self, struct bit_board, ptr);
118
+
119
+ blank = ~(ptr->black | ptr->white);
120
+ bb = ((p << 1) & (blank & 0xFEFEFEFEFEFEFEFE)) |
121
+ ((p >> 1) & (blank & 0x7F7F7F7F7F7F7F7F)) |
122
+ ((p << 8) & (blank & 0xFFFFFFFFFFFFFFFF)) |
123
+ ((p >> 8) & (blank & 0xFFFFFFFFFFFFFFFF)) |
124
+ ((p << 7) & (blank & 0x7F7F7F7F7F7F7F7F)) |
125
+ ((p >> 7) & (blank & 0xFEFEFEFEFEFEFEFE)) |
126
+ ((p << 9) & (blank & 0xFEFEFEFEFEFEFEFE)) |
127
+ ((p >> 9) & (blank & 0x7F7F7F7F7F7F7F7F));
128
+ bb = (bb & 0x5555555555555555) + (bb >> 1 & 0x5555555555555555);
129
+ bb = (bb & 0x3333333333333333) + (bb >> 2 & 0x3333333333333333);
130
+ bb = (bb & 0x0F0F0F0F0F0F0F0F) + (bb >> 4 & 0x0F0F0F0F0F0F0F0F);
131
+ bb = (bb & 0x00FF00FF00FF00FF) + (bb >> 8 & 0x00FF00FF00FF00FF);
132
+ bb = (bb & 0x0000FFFF0000FFFF) + (bb >> 16 & 0x0000FFFF0000FFFF);
133
+ return INT2FIX((int)((bb & 0x00000000FFFFFFFF) + (bb >> 32 & 0x00000000FFFFFFFF)));
134
+ }
135
+
136
+ /*
137
+ * Returns the color of supplied coordinates.
138
+ *
139
+ * @param rb_x [Integer] the column number
140
+ * @param rb_y [Integer] the row number
141
+ * @return [Symbol] the color or `:none`
142
+ */
143
+ VALUE at(VALUE self, VALUE rb_x, VALUE rb_y) {
144
+ unsigned long p = XY2BB(FIX2INT(rb_x), FIX2INT(rb_y));
145
+ struct bit_board *ptr;
146
+ Data_Get_Struct(self, struct bit_board, ptr);
147
+
148
+ if ((p & ptr->black) != 0) { return ID2SYM(rb_intern("black")); }
149
+ else if ((p & ptr->white) != 0) { return ID2SYM(rb_intern("white")); }
150
+ else { return ID2SYM(rb_intern("none")); }
151
+ }
152
+
153
+ /*
154
+ * Counts the number of the supplied color's disks.
155
+ *
156
+ * @param color [Integer]
157
+ * @return [Integer] the sum of the counted disks
158
+ */
159
+ VALUE count_disks(VALUE self, VALUE color) {
160
+ unsigned long bb = 0;
161
+ struct bit_board *ptr;
162
+ Data_Get_Struct(self, struct bit_board, ptr);
163
+
164
+ switch (FIX2INT(color)) {
165
+ case -1: bb = ptr->black; break;
166
+ case 1: bb = ptr->white; break;
167
+ default: bb = ~(ptr->black | ptr->white); break;
168
+ }
169
+ bb = (bb & 0x5555555555555555) + (bb >> 1 & 0x5555555555555555);
170
+ bb = (bb & 0x3333333333333333) + (bb >> 2 & 0x3333333333333333);
171
+ bb = (bb & 0x0F0F0F0F0F0F0F0F) + (bb >> 4 & 0x0F0F0F0F0F0F0F0F);
172
+ bb = (bb & 0x00FF00FF00FF00FF) + (bb >> 8 & 0x00FF00FF00FF00FF);
173
+ bb = (bb & 0x0000FFFF0000FFFF) + (bb >> 16 & 0x0000FFFF0000FFFF);
174
+ return INT2FIX((int)((bb & 0x00000000FFFFFFFF) + (bb >> 32 & 0x00000000FFFFFFFF)));
175
+ }
176
+
177
+ /*
178
+ * Returns an array of the next moves.
179
+ *
180
+ * @param color [Integer]
181
+ * @return [Array<Array<Integer, Integer>>]
182
+ */
183
+ VALUE next_moves(VALUE self, VALUE color) {
184
+ unsigned long my = 0, op = 0, blank = 0, p = 0, pos = 0;
185
+ VALUE moves = rb_ary_new();
186
+ struct bit_board *ptr;
187
+ Data_Get_Struct(self, struct bit_board, ptr);
188
+
189
+ switch (FIX2INT(color)) {
190
+ case -1: my = ptr->black; op = ptr->white; break;
191
+ case 1: my = ptr->white; op = ptr->black; break;
192
+ }
193
+ blank = ~(my | op);
194
+ pos = horizontal_pos(my, op, blank) | vertical_pos(my, op, blank) | diagonal_pos(my, op, blank);
195
+ while (pos != 0) {
196
+ p = pos & (~pos + 1);
197
+ rb_ary_push(moves, BB2XY(p));
198
+ pos ^= p;
199
+ }
200
+ return moves;
201
+ }
202
+
203
+ /*
204
+ * Places a supplied color's disk on specified position.
205
+ *
206
+ * @param rb_x [Integer] the column number
207
+ * @param rb_y [Integer] the row number
208
+ * @param color [Integer]
209
+ */
210
+ VALUE put_disk(VALUE self, VALUE rb_x, VALUE rb_y, VALUE color) {
211
+ unsigned long p = XY2BB(FIX2INT(rb_x), FIX2INT(rb_y));
212
+ struct bit_board *ptr;
213
+ Data_Get_Struct(self, struct bit_board, ptr);
214
+
215
+ switch (FIX2INT(color)) {
216
+ case -1: ptr->black ^= p; break;
217
+ case 1: ptr->white ^= p; break;
218
+ }
219
+ return Qnil;
220
+ }
221
+
222
+ /*
223
+ * Flips the opponent's disks between a new disk and another disk of my color.
224
+ * The invalid move has no effect.
225
+ *
226
+ * @param rb_x [Integer] the column number
227
+ * @param rb_y [Integer] the row number
228
+ * @param color [Integer]
229
+ */
230
+ VALUE flip_disks(VALUE self, VALUE rb_x, VALUE rb_y, VALUE color) {
231
+ unsigned long p = XY2BB(FIX2INT(rb_x), FIX2INT(rb_y));
232
+ unsigned long my = 0, op = 0, rev = 0;
233
+ struct bit_board *ptr;
234
+ Data_Get_Struct(self, struct bit_board, ptr);
235
+
236
+ switch(FIX2INT(color)) {
237
+ case -1:
238
+ my = ptr->black; op = ptr->white;
239
+ if (((ptr->black | ptr->white) & p) != 0) { rev = 0; }
240
+ else { rev = horizontal_pat(my, op, p) | vertical_pat(my, op, p) | diagonal_pat(my, op, p); }
241
+ ptr->black = (ptr->black ^ (p | rev));
242
+ ptr->white = (ptr->white ^ rev);
243
+ break;
244
+ case 1:
245
+ my = ptr->white; op = ptr->black;
246
+ if (((ptr->black | ptr->white) & p) != 0) { rev = 0; }
247
+ else { rev = horizontal_pat(my, op, p) | vertical_pat(my, op, p) | diagonal_pat(my, op, p); }
248
+ ptr->white = (ptr->white ^ (p | rev));
249
+ ptr->black = (ptr->black ^ rev);
250
+ break;
251
+ }
252
+ return Qnil;
253
+ }
@@ -0,0 +1,27 @@
1
+ #ifndef RUBY_BOARD_H
2
+ #define RUBY_BOARD_H
3
+
4
+ #include "reversi.h"
5
+
6
+ struct bit_board {
7
+ unsigned long black;
8
+ unsigned long white;
9
+ };
10
+
11
+ VALUE bit_board_alloc(VALUE class);
12
+ VALUE board_initialize(VALUE self);
13
+
14
+ VALUE black_setter(VALUE self, VALUE black);
15
+ VALUE white_setter(VALUE self, VALUE white);
16
+ VALUE black_getter(VALUE self);
17
+ VALUE white_getter(VALUE self);
18
+
19
+ VALUE status(VALUE self);
20
+ VALUE openness(VALUE self, VALUE rb_x, VALUE rb_y);
21
+ VALUE at(VALUE self, VALUE rb_x, VALUE rb_y);
22
+ VALUE count_disks(VALUE self, VALUE color);
23
+ VALUE next_moves(VALUE self, VALUE color);
24
+ VALUE put_disk(VALUE self, VALUE rb_x, VALUE rb_y, VALUE color);
25
+ VALUE flip_disks(VALUE self, VALUE rb_x, VALUE rb_y, VALUE color);
26
+
27
+ #endif