OSDN Git Service

New feature: Zero least time per move.
[shogi-server/shogi-server.git] / shogi_server / piece.rb
1 ## $Id$
2
3 ## Copyright (C) 2004 NABEYA Kenichi (aka nanami@2ch)
4 ## Copyright (C) 2007-2012 Daigo Moriwaki (daigo at debian dot org)
5 ##
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 2 of the License, or
9 ## (at your option) any later version.
10 ##
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ## GNU General Public License for more details.
15 ##
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, write to the Free Software
18 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 module ShogiServer # for a namespace
21
22 class Piece
23   PROMOTE = {"FU" => "TO", "KY" => "NY", "KE" => "NK", 
24              "GI" => "NG", "KA" => "UM", "HI" => "RY"}
25   def initialize(board, x, y, sente, promoted=false)
26     @board = board
27     @x = x
28     @y = y
29     @sente = sente
30     @promoted = promoted
31
32     if ((x == 0) || (y == 0))
33       if (sente)
34         hands = board.sente_hands
35       else
36         hands = board.gote_hands
37       end
38       hands.push(self)
39       hands.sort! {|a, b|
40         a.name <=> b.name
41       }
42     else
43       @board.array[x][y] = self
44     end
45   end
46   attr_accessor :promoted, :sente, :x, :y, :board
47
48   def room_of_head?(x, y, name)
49     true
50   end
51
52   def movable_grids
53     return adjacent_movable_grids + far_movable_grids
54   end
55
56   def far_movable_grids
57     return []
58   end
59
60   def jump_to?(x, y)
61     if ((1 <= x) && (x <= 9) && (1 <= y) && (y <= 9))
62       if ((@board.array[x][y] == nil) || # dst is empty
63           (@board.array[x][y].sente != @sente)) # dst is enemy
64         return true
65       end
66     end
67     return false
68   end
69
70   def put_to?(x, y)
71     if ((1 <= x) && (x <= 9) && (1 <= y) && (y <= 9))
72       if (@board.array[x][y] == nil) # dst is empty?
73         return true
74       end
75     end
76     return false
77   end
78
79   def adjacent_movable_grids
80     grids = Array::new
81     if (@promoted)
82       moves = @promoted_moves
83     else
84       moves = @normal_moves
85     end
86     moves.each do |(dx, dy)|
87       if (@sente)
88         cand_y = @y - dy
89       else
90         cand_y = @y + dy
91       end
92       cand_x = @x + dx
93       if (jump_to?(cand_x, cand_y))
94         grids.push([cand_x, cand_y])
95       end
96     end
97     return grids
98   end
99
100   def move_to?(x, y, name)
101     return false if (! room_of_head?(x, y, name))
102     return false if ((name != @name) && (name != @promoted_name))
103     return false if (@promoted && (name != @promoted_name)) # can't un-promote
104
105     if (! @promoted)
106       return false if (((@x == 0) || (@y == 0)) && (name != @name)) # can't put promoted piece
107       if (@sente)
108         return false if ((4 <= @y) && (4 <= y) && (name != @name)) # can't promote
109       else
110         return false if ((6 >= @y) && (6 >= y) && (name != @name))
111       end
112     end
113
114     if ((@x == 0) || (@y == 0))
115       return jump_to?(x, y)
116     else
117       return movable_grids.include?([x, y])
118     end
119   end
120
121   def move_to(x, y)
122     if ((@x == 0) || (@y == 0))
123       if (@sente)
124         @board.sente_hands.delete(self)
125       else
126         @board.gote_hands.delete(self)
127       end
128       @board.array[x][y] = self
129     elsif ((x == 0) || (y == 0))
130       @promoted = false         # clear promoted flag before moving to hands
131       if (@sente)
132         @board.sente_hands.push(self)
133       else
134         @board.gote_hands.push(self)
135       end
136       @board.array[@x][@y] = nil
137     else
138       @board.array[@x][@y] = nil
139       @board.array[x][y] = self
140     end
141     @x = x
142     @y = y
143   end
144
145   def point
146     @point
147   end
148
149   def name
150     @name
151   end
152
153   def promoted_name
154     @promoted_name
155   end
156
157   def current_name
158     return @promoted ? @promoted_name : @name
159   end
160
161   def to_s
162     if (@sente)
163       sg = "+"
164     else
165       sg = "-"
166     end
167     return sg + current_name
168   end
169 end
170
171 class PieceFU < Piece
172   def initialize(*arg)
173     @point = 1
174     @normal_moves = [[0, +1]]
175     @promoted_moves = [[0, +1], [+1, +1], [-1, +1], [+1, +0], [-1, +0], [0, -1]]
176     @name = "FU"
177     @promoted_name = "TO"
178     super
179   end
180   def room_of_head?(x, y, name)
181     if (name == "FU")
182       if (@sente)
183         return false if (y == 1)
184       else
185         return false if (y == 9)
186       end
187       ## 2fu check
188       c = 0
189       iy = 1
190       while (iy <= 9)
191         if ((iy  != @y) &&      # not source position
192             @board.array[x][iy] &&
193             (@board.array[x][iy].sente == @sente) && # mine
194             (@board.array[x][iy].name == "FU") &&
195             (@board.array[x][iy].promoted == false))
196           return false
197         end
198         iy = iy + 1
199       end
200     end
201     return true
202   end
203 end
204
205 class PieceKY  < Piece
206   def initialize(*arg)
207     @point = 1
208     @normal_moves = []
209     @promoted_moves = [[0, +1], [+1, +1], [-1, +1], [+1, +0], [-1, +0], [0, -1]]
210     @name = "KY"
211     @promoted_name = "NY"
212     super
213   end
214   def room_of_head?(x, y, name)
215     if (name == "KY")
216       if (@sente)
217         return false if (y == 1)
218       else
219         return false if (y == 9)
220       end
221     end
222     return true
223   end
224   def far_movable_grids
225     grids = Array::new
226     if (@promoted)
227       return []
228     else
229       if (@sente)                 # up
230         cand_x = @x
231         cand_y = @y - 1
232         while (jump_to?(cand_x, cand_y))
233           grids.push([cand_x, cand_y])
234           break if (! put_to?(cand_x, cand_y))
235           cand_y = cand_y - 1
236         end
237       else                        # down
238         cand_x = @x
239         cand_y = @y + 1
240         while (jump_to?(cand_x, cand_y))
241           grids.push([cand_x, cand_y])
242           break if (! put_to?(cand_x, cand_y))
243           cand_y = cand_y + 1
244         end
245       end
246       return grids
247     end
248   end
249 end
250
251 class PieceKE  < Piece
252   def initialize(*arg)
253     @point = 1
254     @normal_moves = [[+1, +2], [-1, +2]]
255     @promoted_moves = [[0, +1], [+1, +1], [-1, +1], [+1, +0], [-1, +0], [0, -1]]
256     @name = "KE"
257     @promoted_name = "NK"
258     super
259   end
260   def room_of_head?(x, y, name)
261     if (name == "KE")
262       if (@sente)
263         return false if ((y == 1) || (y == 2))
264       else
265         return false if ((y == 9) || (y == 8))
266       end
267     end
268     return true
269   end
270 end
271 class PieceGI  < Piece
272   def initialize(*arg)
273     @point = 1
274     @normal_moves = [[0, +1], [+1, +1], [-1, +1], [+1, -1], [-1, -1]]
275     @promoted_moves = [[0, +1], [+1, +1], [-1, +1], [+1, +0], [-1, +0], [0, -1]]
276     @name = "GI"
277     @promoted_name = "NG"
278     super
279   end
280 end
281 class PieceKI  < Piece
282   def initialize(*arg)
283     @point = 1
284     @normal_moves = [[0, +1], [+1, +1], [-1, +1], [+1, +0], [-1, +0], [0, -1]]
285     @promoted_moves = []
286     @name = "KI"
287     @promoted_name = nil
288     super
289   end
290 end
291 class PieceKA  < Piece
292   def initialize(*arg)
293     @point = 5
294     @normal_moves = []
295     @promoted_moves = [[0, +1], [+1, 0], [-1, 0], [0, -1]]
296     @name = "KA"
297     @promoted_name = "UM"
298     super
299   end
300   def far_movable_grids
301     grids = Array::new
302     ## up right
303     cand_x = @x - 1
304     cand_y = @y - 1
305     while (jump_to?(cand_x, cand_y))
306       grids.push([cand_x, cand_y])
307       break if (! put_to?(cand_x, cand_y))
308       cand_x = cand_x - 1
309       cand_y = cand_y - 1
310     end
311     ## down right
312     cand_x = @x - 1
313     cand_y = @y + 1
314     while (jump_to?(cand_x, cand_y))
315       grids.push([cand_x, cand_y])
316       break if (! put_to?(cand_x, cand_y))
317       cand_x = cand_x - 1
318       cand_y = cand_y + 1
319     end
320     ## up left
321     cand_x = @x + 1
322     cand_y = @y - 1
323     while (jump_to?(cand_x, cand_y))
324       grids.push([cand_x, cand_y])
325       break if (! put_to?(cand_x, cand_y))
326       cand_x = cand_x + 1
327       cand_y = cand_y - 1
328     end
329     ## down left
330     cand_x = @x + 1
331     cand_y = @y + 1
332     while (jump_to?(cand_x, cand_y))
333       grids.push([cand_x, cand_y])
334       break if (! put_to?(cand_x, cand_y))
335       cand_x = cand_x + 1
336       cand_y = cand_y + 1
337     end
338     return grids
339   end
340 end
341 class PieceHI  < Piece
342   def initialize(*arg)
343     @point = 5
344     @normal_moves = []
345     @promoted_moves = [[+1, +1], [-1, +1], [+1, -1], [-1, -1]]
346     @name = "HI"
347     @promoted_name = "RY"
348     super
349   end
350   def far_movable_grids
351     grids = Array::new
352     ## up
353     cand_x = @x
354     cand_y = @y - 1
355     while (jump_to?(cand_x, cand_y))
356       grids.push([cand_x, cand_y])
357       break if (! put_to?(cand_x, cand_y))
358       cand_y = cand_y - 1
359     end
360     ## down
361     cand_x = @x
362     cand_y = @y + 1
363     while (jump_to?(cand_x, cand_y))
364       grids.push([cand_x, cand_y])
365       break if (! put_to?(cand_x, cand_y))
366       cand_y = cand_y + 1
367     end
368     ## right
369     cand_x = @x - 1
370     cand_y = @y
371     while (jump_to?(cand_x, cand_y))
372       grids.push([cand_x, cand_y])
373       break if (! put_to?(cand_x, cand_y))
374       cand_x = cand_x - 1
375     end
376     ## down
377     cand_x = @x + 1
378     cand_y = @y
379     while (jump_to?(cand_x, cand_y))
380       grids.push([cand_x, cand_y])
381       break if (! put_to?(cand_x, cand_y))
382       cand_x = cand_x + 1
383     end
384     return grids
385   end
386 end
387 class PieceOU < Piece
388   def initialize(*arg)
389     @point = 0
390     @normal_moves = [[0, +1], [+1, +1], [-1, +1], [+1, +0], [-1, +0], [0, -1], [+1, -1], [-1, -1]]
391     @promoted_moves = []
392     @name = "OU"
393     @promoted_name = nil
394     super
395     @board.add_ou(self)
396   end
397 end
398
399 end # ShogiServer