Class: EightyOne::Board

Inherits:
Object
  • Object
show all
Includes:
Helper
Defined in:
lib/eighty_one/board.rb

Defined Under Namespace

Classes: Movement

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helper

#assert

Constructor Details

#initializeBoard

Returns a new instance of Board.



5
6
7
8
# File 'lib/eighty_one/board.rb', line 5

def initialize
  @board = Array.new(81)
  @hands = Struct.new(:sente, :gote).new([], [])
end

Class Method Details

.decode(code) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/eighty_one/board.rb', line 131

def self.decode(code)
  board = Board.new
  (board_map, pieces) = code.unpack('a21a*')
  (on_board, hands) = pieces.split(?/).map{|x| x.chars.each_slice(3).map(&:join) }

  code[0,21].to_i(16).to_s(2).chars.each_slice(9).with_index do |row, y|
    row.each_with_index do |cell, x|
      board[9 - x, y + 1] = Piece.decode(on_board.shift) if cell == '1'
    end
  end

  hands.map{|s| Piece.decode(s) }.each do |piece|
    case piece.turn
      when :sente
        board.sente_hands << piece
      when :gote
        board.gote_hands << piece
    end
  end
  board
end

Instance Method Details

#[](col, row) ⇒ Object Also known as: at



63
64
65
# File 'lib/eighty_one/board.rb', line 63

def [](col, row)
  @board[(row - 1) * 9 + 9 - col]
end

#[]=(col, row, value) ⇒ Object



57
58
59
60
61
# File 'lib/eighty_one/board.rb', line 57

def []=(col, row, value)
  assert(inside?(col, row))
  assert(value.nil? || Piece === value)
  @board[(row - 1) * 9 + 9 - col] = value
end

#can_move_to_any_place?(piece, col, row) ⇒ Boolean

Returns:

  • (Boolean)


47
48
49
# File 'lib/eighty_one/board.rb', line 47

def can_move_to_any_place?(piece, col, row)
  !([:FU, :KY].include?(piece.face.symbol) && (piece.sente? ? col == 1 : col == 9))
end

#capture(piece) ⇒ Object



103
104
105
# File 'lib/eighty_one/board.rb', line 103

def capture(piece)
  @hands[piece.turn] << piece
end

#dests_from(col, row) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/eighty_one/board.rb', line 81

def dests_from(col, row)
  piece = self.at(col, row)
  assert(Piece === piece)
  dest = Proc.new{|(c, r)| [col + c, piece.sente? ? row - r : row + r] }
  piece.face.movements.map do |m|
    if EightyOne::Faces::Direction === m
      captured = false
      m.map{|p| dest[p] }.take_while do |p|
        (!captured && placeable?(piece, *p)).tap do |x|
          captured = x && self.at(*p)
        end
      end
    else
      dest[m].yield_self{|p| placeable?(piece, *p) ? [p] : [] }
    end
  end.flatten(1)
end

#double_fu?(piece, col, row) ⇒ Boolean

Returns:

  • (Boolean)


43
44
45
# File 'lib/eighty_one/board.rb', line 43

def double_fu?(piece, col, row)
  piece.face.symbol == :FU && (1..9).any?{|i| self[i, row]&.yield_self{|p| p.face.symbol == :FU && p.turn == piece.turn } }
end

#encodeObject



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/eighty_one/board.rb', line 117

def encode
  board_map = (0..81).step(4).map do |i|
    @board.slice(i, 4).map.with_index{|piece, i| (piece ? 1 : 0) << (3 - i) }.sum.to_s(16)
  end.join

  on_board = (1..9).map do |row|
    row(row).compact.map(&:to_s).join
  end.join

  hands = @hands.sente.map(&:to_s).join + @hands.gote.map(&:to_s).join

  board_map + on_board + ?/ + hands
end

#gote_handsObject



71
72
73
# File 'lib/eighty_one/board.rb', line 71

def gote_hands
  @hands.gote
end

#initial_stateObject



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/eighty_one/board.rb', line 10

def initial_state
  (1..9).each do |i|
    self[i, 7] = Pieces::Fu.new(:sente)
    self[i, 3] = Pieces::Fu.new(:gote)
  end
  [1, 9].each do |i|
    self[i, 9] = Pieces::Ky.new(:sente)
    self[i, 1] = Pieces::Ky.new(:gote)
  end
  [2, 8].each do |i|
    self[i, 9] = Pieces::Ke.new(:sente)
    self[i, 1] = Pieces::Ke.new(:gote)
  end
  [3, 7].each do |i|
    self[i, 9] = Pieces::Gi.new(:sente)
    self[i, 1] = Pieces::Gi.new(:gote)
  end
  [4, 6].each do |i|
    self[i, 9] = Pieces::Ki.new(:sente)
    self[i, 1] = Pieces::Ki.new(:gote)
  end
  self[2, 8] = Pieces::Ka.new(:sente)
  self[8, 2] = Pieces::Ka.new(:gote)
  self[8, 8] = Pieces::Hi.new(:sente)
  self[2, 2] = Pieces::Hi.new(:gote)
  self[5, 9] = Pieces::Ou.new(:sente)
  self[5, 1] = Pieces::Ou.new(:gote)
end

#inside?(col, row) ⇒ Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/eighty_one/board.rb', line 39

def inside?(col, row)
  1 <= row && 9 >= row && 1 <= col && 9 >= col
end

#move_from(col, row) ⇒ Object



99
100
101
# File 'lib/eighty_one/board.rb', line 99

def move_from(col, row)
  Movement.new(self, col, row)
end

#place(piece, col, row) ⇒ Object



107
108
109
110
111
112
113
114
115
# File 'lib/eighty_one/board.rb', line 107

def place(piece, col, row)
  dest = self.at(col, row)
  if dest
    assert(Piece === dest)
    assert(dest.turn != piece.turn)
    capture(dest.reset(piece.turn))
  end
  self[col, row] = piece
end

#placeable?(piece, col, row, from_hand = false) ⇒ Boolean

Returns:

  • (Boolean)


51
52
53
54
55
# File 'lib/eighty_one/board.rb', line 51

def placeable?(piece, col, row, from_hand = false)
  res = inside?(col, row) && !(self[col, row]&.turn == piece.turn)
  res &&= can_move_to_any_place?(piece, col, row) && !double_fu?(piece, col, row) if from_hand
  res
end

#row(row) ⇒ Object



77
78
79
# File 'lib/eighty_one/board.rb', line 77

def row(row)
  @board[(row - 1) * 9, 9].reverse
end

#sente_handsObject



67
68
69
# File 'lib/eighty_one/board.rb', line 67

def sente_hands
  @hands.sente
end

#to_csiObject



153
154
155
156
157
# File 'lib/eighty_one/board.rb', line 153

def to_csi
  (1..9).map do |i|
    "P#{i}" + row(i).map{|c| c ? c.to_s : ' * '}.join
  end.join(?\n)
end

#to_sObject



159
160
161
# File 'lib/eighty_one/board.rb', line 159

def to_s
  self.to_csi
end