• R/O
  • HTTP
  • SSH
  • HTTPS

shogi-server: コミット

shogi-server source


コミットメタ情報

リビジョン48caf92ecf5d5669a5ccef83bf351f612e8aab70 (tree)
日時2013-12-13 15:09:35
作者Daigo Moriwaki <daigo@debi...>
コミッターDaigo Moriwaki

ログメッセージ

[shogi-server] - Implemented conversion of move representation between CSA format and USI one.

変更サマリ

差分

--- a/changelog
+++ b/changelog
@@ -1,3 +1,9 @@
1+2013-12-13 Daigo Moriwaki <daigo at debian dot org>
2+
3+ * [shogi-server]
4+ - Implemented conversion of move representation between CSA format
5+ and USI one.
6+
17 2013-11-24 Daigo Moriwaki <daigo at debian dot org>
28
39 * [shogi-server]
--- a/shogi_server/board.rb
+++ b/shogi_server/board.rb
@@ -94,6 +94,7 @@ EOF
9494 @move_count = move_count
9595 @teban = nil # black => true, white => false
9696 @initial_moves = []
97+ @move = nil
9798 @ous = [nil, nil] # keep OU pieces of Sente and Gote
9899 end
99100 attr_accessor :array, :sente_hands, :gote_hands, :history, :sente_history, :gote_history, :teban
@@ -104,6 +105,11 @@ EOF
104105 # moves.
105106 attr_reader :initial_moves
106107
108+ # A move parsed by handle_one_move. If the move is not :normal, the board
109+ # position may or may not be rolled back.
110+ #
111+ attr_reader :move
112+
107113 # See if self equals rhs, including a logical board position (i.e.
108114 # not see object IDs) and sennichite stuff.
109115 #
@@ -678,18 +684,18 @@ EOF
678684 return :illegal # can't put on existing piece
679685 end
680686
681- move = Move.new(x0, y0, x1, y1, name, sente)
682- result = move_to(move)
687+ @move = Move.new(x0, y0, x1, y1, name, sente)
688+ result = move_to(@move)
683689 if (result == :illegal)
684690 # self is unchanged
685691 return :illegal
686692 end
687693 if (checkmated?(sente))
688- move_back(move)
694+ move_back(@move)
689695 return :oute_kaihimore
690696 end
691697 if ((x0 == 0) && (y0 == 0) && (name == "FU") && uchifuzume?(sente))
692- move_back(move)
698+ move_back(@move)
693699 return :uchifuzume
694700 end
695701
@@ -697,12 +703,12 @@ EOF
697703 update_sennichite(sente)
698704 os_result = oute_sennichite?(sente)
699705 if os_result # :oute_sennichite_sente_lose or :oute_sennichite_gote_lose
700- move_back(move)
706+ move_back(@move)
701707 restore_sennichite_stuff(*sennichite_stuff)
702708 return os_result
703709 end
704710 if sennichite?
705- move_back(move)
711+ move_back(@move)
706712 restore_sennichite_stuff(*sennichite_stuff)
707713 return :sennichite
708714 end
--- a/shogi_server/piece.rb
+++ b/shogi_server/piece.rb
@@ -154,18 +154,17 @@ class Piece
154154 @promoted_name
155155 end
156156
157+ def current_name
158+ return @promoted ? @promoted_name : @name
159+ end
160+
157161 def to_s
158162 if (@sente)
159163 sg = "+"
160164 else
161165 sg = "-"
162166 end
163- if (@promoted)
164- n = @promoted_name
165- else
166- n = @name
167- end
168- return sg + n
167+ return sg + current_name
169168 end
170169 end
171170
--- a/shogi_server/usi.rb
+++ b/shogi_server/usi.rb
@@ -13,7 +13,181 @@ module ShogiServer # for a namespace
1313 gsub("@", "+").
1414 gsub(".", " ")
1515 end
16- end
16+
17+ # 1 -> a
18+ # 2 -> b
19+ # ...
20+ # 9 -> i
21+ def danToAlphabet(int)
22+ return (int+96).chr
23+ end
24+
25+ # a -> 1
26+ # b -> 2
27+ # ...
28+ # i -> 9
29+ def alphabetToDan(s)
30+ if RUBY_VERSION >= "1.9.1"
31+ return s.bytes[0]-96
32+ else
33+ return s[0]-96
34+ end
35+ end
36+
37+ def csaPieceToUsi(csa, sente)
38+ str = ""
39+ case csa
40+ when "FU"
41+ str = "p"
42+ when "KY"
43+ str = "l"
44+ when "KE"
45+ str = "n"
46+ when "GI"
47+ str = "s"
48+ when "KI"
49+ str = "g"
50+ when "KA"
51+ str = "b"
52+ when "HI"
53+ str = "r"
54+ when "OU"
55+ str = "k"
56+ when "TO"
57+ str = "+p"
58+ when "NY"
59+ str = "+l"
60+ when "NK"
61+ str = "+n"
62+ when "NG"
63+ str = "+s"
64+ when "UM"
65+ str = "+b"
66+ when "RY"
67+ str = "+r"
68+ end
69+ return sente ? str.upcase : str
70+ end
71+
72+ def usiPieceToCsa(str)
73+ ret = ""
74+ case str.downcase
75+ when "p"
76+ ret = "FU"
77+ when "l"
78+ ret = "KY"
79+ when "n"
80+ ret = "KE"
81+ when "s"
82+ ret = "GI"
83+ when "g"
84+ ret = "KI"
85+ when "b"
86+ ret = "KA"
87+ when "r"
88+ ret = "HI"
89+ when "+p"
90+ ret = "TO"
91+ when "+l"
92+ ret = "NY"
93+ when "+n"
94+ ret = "NK"
95+ when "+s"
96+ ret = "NG"
97+ when "+b"
98+ ret = "UM"
99+ when "+r"
100+ ret = "RY"
101+ when "k"
102+ ret = "OU"
103+ end
104+ return ret
105+ end
106+
107+ def moveToUsi(move)
108+ str = ""
109+ if move.is_drop?
110+ str += "%s*%s%s" % [csaPieceToUsi(move.name, move.sente).upcase, move.x1, danToAlphabet(move.y1)]
111+ else
112+ str += "%s%s%s%s" % [move.x0, danToAlphabet(move.y0), move.x1, danToAlphabet(move.y1)]
113+ str += "+" if move.promotion
114+ end
115+
116+ return str
117+ end
118+
119+ def usiToCsa(str, board, sente)
120+ ret = ""
121+ if str[1..1] == "*"
122+ # drop
123+ ret += "00%s%s%s" % [str[2..2], alphabetToDan(str[3..3]), usiPieceToCsa(str[0..0])]
124+ else
125+ from_x = str[0..0]
126+ from_y = alphabetToDan(str[1..1])
127+ ret += "%s%s%s%s" % [from_x, from_y, str[2..2], alphabetToDan(str[3..3])]
128+ csa_piece = board.array[from_x.to_i][from_y.to_i]
129+ if str.size == 5 && str[4..4] == "+"
130+ # Promoting move
131+ ret += csa_piece.promoted_name
132+ else
133+ ret += csa_piece.current_name
134+ end
135+ end
136+ return (sente ? "+" : "-") + ret
137+ end
138+ end # class methods
139+
140+ # Convert USI moves to CSA one by one from the initial position
141+ #
142+ class UsiToCsa
143+ attr_reader :board, :csa_moves
144+
145+ # Constructor
146+ #
147+ def initialize
148+ @board = ShogiServer::Board.new
149+ @board.initial
150+ @sente = true
151+ @csa_moves = []
152+ end
153+
154+ # Parses a usi move string and returns an array of [move_result_state,
155+ # csa_move_string]
156+ #
157+ def next(usi)
158+ csa = Usi.usiToCsa(usi, @board, @sente)
159+ state = @board.handle_one_move(csa, @sente)
160+ @sente = !@sente
161+ @csa_moves << csa
162+ return [state, csa]
163+ end
164+ end # class UsiToCsa
165+
166+ # Convert CSA moves to USI one by one from the initial position
167+ #
168+ class CsaToUsi
169+ attr_reader :board, :usi_moves
170+
171+ # Constructor
172+ #
173+ def initialize
174+ @board = ShogiServer::Board.new
175+ @board.initial
176+ @sente = true
177+ @usi_moves = []
178+ end
179+
180+ # Parses a csa move string and returns an array of [move_result_state,
181+ # usi_move_string]
182+ #
183+ def next(csa)
184+ state = @board.handle_one_move(csa, @sente)
185+ @sente = !@sente
186+ usi = Usi.moveToUsi(@board.move)
187+ @usi_moves << usi
188+ return [state, usi]
189+ end
190+ end # class CsaToUsi
17191
18192 def charToPiece(c)
19193 player = nil
@@ -164,6 +338,7 @@ module ShogiServer # for a namespace
164338 s += hands2usi(board.gote_hands).downcase
165339 return s
166340 end
341+
167342 end # class
168343
169344 end # module
--- a/test/TC_usi.rb
+++ b/test/TC_usi.rb
@@ -84,4 +84,22 @@ P-00FU00FU
8484 EOB
8585 assert_equal "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b 2p", @usi.board2usi(b, b.teban)
8686 end
87+
88+ def test_usiToCsa
89+ # 26th Ryuousen 5th match Moriuchi vs Watanabe on Nov 28th, 2013
90+ usi_moves = %w!7g7f 8c8d 7i6h 3c3d 6g6f 7a6b 5g5f 5c5d 3i4h 3a4b 4i5h 4a3b 6i7h 5a4a 5i6i 6a5b 6h7g 4b3c 8h7i 2b3a 3g3f 4c4d 4h3g 3a6d 5h6g 7c7d 7i6h 5b4c 6i7i 4a3a 7i8h 9c9d 3g4f 6b5c 2i3g 6d7c 1g1f 1c1d 2g2f 3c2d 2h3h 9d9e 1i1h 3a2b 3g2e 4d4e 4f4e 7c1i+ 6h4f 1i4f 4g4f B*5i B*3g 5i3g+ 3h3g B*1i 3g3h 1i4f+ P*4d 4c4d B*7a 4d4c 6g5g 4f5g 7a8b+ P*4d 4e3d 4c3d R*5a 5c4b 5a8a+ S*6i 7h6h 5g6h 3h6h G*5h 8b4f 5h6h 4f6h R*4h G*7i 6i5h+ 6h7h G*6i 7i6i 5h6i B*5g 4h1h+ P*4h 1h2g 5g2d 3d2d 7h6i L*6g S*6h 6g6h+ 6i6h S*5g N*3c 4b3c 2e3c+ 2b3c L*3e P*3d 8a2a G*3a 2a1a 5g6h 7g6h N*6d S*6g 3d3e S*5c 2g3f N*2e 3c4c 5c6d+ 6c6d G*3c 4c5c 3c3b 3a3b N*5e 5d5e 1a5a L*5b L*5d 5c5d 5a5b 5d4e L*4g 3f4g 4h4g 4e3f G*3h!
91+ uc = ShogiServer::Usi::UsiToCsa.new
92+ usi_moves.each do |m|
93+ state, csa = uc.next(m)
94+ assert_equal(:normal, state)
95+ end
96+
97+ cu = ShogiServer::Usi::CsaToUsi.new
98+ uc.csa_moves.each do |m|
99+ state, usi = cu.next(m)
100+ assert_equal(:normal, state)
101+ end
102+
103+ assert_equal(usi_moves, cu.usi_moves)
104+ end
87105 end
旧リポジトリブラウザで表示