Class: Reversi::Board
- Inherits:
-
Object
- Object
- Reversi::Board
- Defined in:
- lib/reversi/board.rb,
ext/reversi/reversi.c
Constant Summary collapse
- DISK =
{ :none => 0, :black => -1, :white => 1 }.freeze
- DISK_COLOR =
{ :black => 30, :red => 31, :green => 32, :yellow => 33, :blue => 34, :magenda => 35, :cyan => 36, :white => 37, :gray => 90 }.freeze
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#stack ⇒ Object
readonly
Returns the value of attribute stack.
Instance Method Summary collapse
-
#at(rb_x, rb_y) ⇒ Symbol
Returns the color of supplied coordinates.
-
#count_disks(color) ⇒ Integer
Counts the number of the supplied color’s disks.
-
#flip_disks(rb_x, rb_y, color) ⇒ Object
Flips the opponent’s disks between a new disk and another disk of my color.
-
#initialize(options = {}) ⇒ Reversi::Board
constructor
Initializes a new Board object.
-
#next_moves(color) ⇒ Array<Array<Integer, Integer>>
Returns an array of the next moves.
-
#openness(rb_x, rb_y) ⇒ Integer
Returns the openness of the coordinates.
-
#push_stack ⇒ Object
Pushes an array of the game board onto a stack.
-
#put_disk(rb_x, rb_y, color) ⇒ Object
Places a supplied color’s disk on specified position.
-
#status ⇒ Hash{Symbol => Array<Array<Integer, Integer>>}
Returns a hash containing the coordinates of each color.
-
#to_s ⇒ String
Returns a string of the game board in human-readable form.
-
#undo! ⇒ Object
Pops a hash of the game board off of the stack, and that is stored in the instance variable.(‘@bit_board`).
Constructor Details
#initialize(options = {}) ⇒ Reversi::Board
Initializes a new Board object.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/reversi/board.rb', line 29 def initialize( = {}) = @stack = [] board_initialize [:disk_color_b, :disk_color_w].each do |color| if [color].is_a?(Symbol) || [color].is_a?(String) [color] = DISK_COLOR[[color].to_sym].to_i end end [:initial_position].each do |color, positions| positions.each{ |position| put_disk(*position, DISK[color]) } end if [:disk_b].size != 1 || [:disk_w].size != 1 raise OptionError, "The length of the disk string must be one." end end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
3 4 5 |
# File 'lib/reversi/board.rb', line 3 def end |
#stack ⇒ Object (readonly)
Returns the value of attribute stack.
3 4 5 |
# File 'lib/reversi/board.rb', line 3 def stack @stack end |
Instance Method Details
#at(rb_x, rb_y) ⇒ Symbol
Returns the color of supplied coordinates.
143 144 145 146 147 148 149 150 151 |
# File 'ext/reversi/board.c', line 143 VALUE at(VALUE self, VALUE rb_x, VALUE rb_y) { uint64_t p = XY2BB(FIX2INT(rb_x), FIX2INT(rb_y)); struct bit_board *ptr; Data_Get_Struct(self, struct bit_board, ptr); if ((p & ptr->black) != 0) { return ID2SYM(rb_intern("black")); } else if ((p & ptr->white) != 0) { return ID2SYM(rb_intern("white")); } else { return ID2SYM(rb_intern("none")); } } |
#count_disks(color) ⇒ Integer
Counts the number of the supplied color’s disks.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'ext/reversi/board.c', line 159 VALUE count_disks(VALUE self, VALUE color) { uint64_t bb = 0; struct bit_board *ptr; Data_Get_Struct(self, struct bit_board, ptr); switch (FIX2INT(color)) { case -1: bb = ptr->black; break; case 1: bb = ptr->white; break; default: bb = ~(ptr->black | ptr->white); break; } bb = (bb & 0x5555555555555555) + (bb >> 1 & 0x5555555555555555); bb = (bb & 0x3333333333333333) + (bb >> 2 & 0x3333333333333333); bb = (bb & 0x0F0F0F0F0F0F0F0F) + (bb >> 4 & 0x0F0F0F0F0F0F0F0F); bb = (bb & 0x00FF00FF00FF00FF) + (bb >> 8 & 0x00FF00FF00FF00FF); bb = (bb & 0x0000FFFF0000FFFF) + (bb >> 16 & 0x0000FFFF0000FFFF); return INT2FIX((int)((bb & 0x00000000FFFFFFFF) + (bb >> 32 & 0x00000000FFFFFFFF))); } |
#flip_disks(rb_x, rb_y, color) ⇒ Object
Flips the opponent’s disks between a new disk and another disk of my color. This method is used in Reversi::Player::BasePlayer class. When the invalid move is supplied, a disk is put only the position and Reversi::MoveError is raised at Reversi::Game.check_move method.
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'ext/reversi/board.c', line 236 VALUE flip_disks(VALUE self, VALUE rb_x, VALUE rb_y, VALUE color) { uint64_t p = XY2BB(FIX2INT(rb_x), FIX2INT(rb_y)); uint64_t my = 0, op = 0, rev = 0; struct bit_board *ptr; Data_Get_Struct(self, struct bit_board, ptr); switch(FIX2INT(color)) { case -1: my = ptr->black; op = ptr->white; if (((ptr->black | ptr->white) & p) != 0) { rev = 0; } else { rev = horizontal_pat(my, op, p) | vertical_pat(my, op, p) | diagonal_pat(my, op, p); } ptr->black = (ptr->black ^ (p | rev)); ptr->white = (ptr->white ^ rev); break; case 1: my = ptr->white; op = ptr->black; if (((ptr->black | ptr->white) & p) != 0) { rev = 0; } else { rev = horizontal_pat(my, op, p) | vertical_pat(my, op, p) | diagonal_pat(my, op, p); } ptr->white = (ptr->white ^ (p | rev)); ptr->black = (ptr->black ^ rev); break; } return Qnil; } |
#next_moves(color) ⇒ Array<Array<Integer, Integer>>
Returns an array of the next moves. This method is used in Reversi::Player::BasePlayer class.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'ext/reversi/board.c', line 184 VALUE next_moves(VALUE self, VALUE color) { uint64_t my = 0, op = 0, blank = 0, p = 0, pos = 0; VALUE moves = rb_ary_new(); struct bit_board *ptr; Data_Get_Struct(self, struct bit_board, ptr); switch (FIX2INT(color)) { case -1: my = ptr->black; op = ptr->white; break; case 1: my = ptr->white; op = ptr->black; break; } blank = ~(my | op); pos = horizontal_pos(my, op, blank) | vertical_pos(my, op, blank) | diagonal_pos(my, op, blank); while (pos != 0) { p = pos & (~pos + 1); rb_ary_push(moves, BB2XY(p)); pos ^= p; } return moves; } |
#openness(rb_x, rb_y) ⇒ Integer
Returns the openness of the coordinates.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'ext/reversi/board.c', line 113 VALUE openness(VALUE self, VALUE rb_x, VALUE rb_y) { uint64_t p = XY2BB(FIX2INT(rb_x), FIX2INT(rb_y)); uint64_t blank = 0, bb = 0; struct bit_board *ptr; Data_Get_Struct(self, struct bit_board, ptr); blank = ~(ptr->black | ptr->white); bb = ((p << 1) & (blank & 0xFEFEFEFEFEFEFEFE)) | ((p >> 1) & (blank & 0x7F7F7F7F7F7F7F7F)) | ((p << 8) & (blank & 0xFFFFFFFFFFFFFFFF)) | ((p >> 8) & (blank & 0xFFFFFFFFFFFFFFFF)) | ((p << 7) & (blank & 0x7F7F7F7F7F7F7F7F)) | ((p >> 7) & (blank & 0xFEFEFEFEFEFEFEFE)) | ((p << 9) & (blank & 0xFEFEFEFEFEFEFEFE)) | ((p >> 9) & (blank & 0x7F7F7F7F7F7F7F7F)); bb = (bb & 0x5555555555555555) + (bb >> 1 & 0x5555555555555555); bb = (bb & 0x3333333333333333) + (bb >> 2 & 0x3333333333333333); bb = (bb & 0x0F0F0F0F0F0F0F0F) + (bb >> 4 & 0x0F0F0F0F0F0F0F0F); bb = (bb & 0x00FF00FF00FF00FF) + (bb >> 8 & 0x00FF00FF00FF00FF); bb = (bb & 0x0000FFFF0000FFFF) + (bb >> 16 & 0x0000FFFF0000FFFF); return INT2FIX((int)((bb & 0x00000000FFFFFFFF) + (bb >> 32 & 0x00000000FFFFFFFF))); } |
#push_stack ⇒ Object
Pushes an array of the game board onto a stack. The stack size limit is 3(default).
71 72 73 74 75 |
# File 'lib/reversi/board.rb', line 71 def push_stack bb = {:black => get_black,:white => get_white} @stack.push(Marshal.load(Marshal.dump(bb))) @stack.shift if @stack.size > [:stack_limit] end |
#put_disk(rb_x, rb_y, color) ⇒ Object
Places a supplied color’s disk on specified position. This method is used in Reversi::Board.initialize method for putting the disks at the initial position, but not used in Reversi::Player::BasePlayer class.
214 215 216 217 218 219 220 221 222 223 224 |
# File 'ext/reversi/board.c', line 214 VALUE put_disk(VALUE self, VALUE rb_x, VALUE rb_y, VALUE color) { uint64_t p = XY2BB(FIX2INT(rb_x), FIX2INT(rb_y)); struct bit_board *ptr; Data_Get_Struct(self, struct bit_board, ptr); switch (FIX2INT(color)) { case -1: ptr->black ^= p; break; case 1: ptr->white ^= p; break; } return Qnil; } |
#status ⇒ Hash{Symbol => Array<Array<Integer, Integer>>}
Returns a hash containing the coordinates of each color.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'ext/reversi/board.c', line 70 VALUE status(VALUE self) { VALUE black_ary = rb_ary_new(); VALUE white_ary = rb_ary_new(); VALUE none_ary = rb_ary_new(); VALUE status = rb_hash_new(); uint64_t black = 0, white = 0, blank = 0, p = 0; struct bit_board *ptr; Data_Get_Struct(self, struct bit_board, ptr); black = ptr->black; while (black != 0) { p = black & (~black + 1); rb_ary_push(black_ary, BB2XY(p)); black ^= p; } rb_hash_aset(status, ID2SYM(rb_intern("black")), black_ary); white = ptr->white; while (white != 0) { p = white & (~white + 1); rb_ary_push(white_ary, BB2XY(p)); white ^= p; } rb_hash_aset(status, ID2SYM(rb_intern("white")), white_ary); blank = ~(ptr->black | ptr->white); while (blank != 0) { p = blank & (~blank + 1); rb_ary_push(none_ary, BB2XY(p)); blank ^= p; } rb_hash_aset(status, ID2SYM(rb_intern("none")), none_ary); return status; } |
#to_s ⇒ String
Returns a string of the game board in human-readable form.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/reversi/board.rb', line 52 def to_s " #{[*'a'..'h'].join(" ")}\n" << " #{"+---"*8}+\n" << (0..63).map do |i| case 1 when get_black[63 - i] then "\e[#{@options[:disk_color_b]}m#{@options[:disk_b]}\e[0m" when get_white[63 - i] then "\e[#{@options[:disk_color_w]}m#{@options[:disk_w]}\e[0m" else " " end end .map{ |e| "| #{e} |" }.each_slice(8).map(&:join) .map{ |line| line.gsub(/\|\|/, "|") } .tap{ |lines| break (0..7).map{ |i| " #{i+1} #{lines[i]}" } } .join("\n #{"+---"*8}+\n") << "\n #{"+---"*8}+\n" end |
#undo! ⇒ Object
Pops a hash of the game board off of the stack, and that is stored in the instance variable.(‘@bit_board`)
79 80 81 82 83 |
# File 'lib/reversi/board.rb', line 79 def undo! bb = @stack.pop set_black(bb[:black]) set_white(bb[:white]) end |