From 93ea49f6255681f8a4dbf0d85a6581ff4ddd250e Mon Sep 17 00:00:00 2001 From: nabeken Date: Sat, 10 Jul 2004 19:16:30 +0000 Subject: [PATCH] sennichite check added --- shogi-server | 139 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 93 insertions(+), 46 deletions(-) diff --git a/shogi-server b/shogi-server index 992c5d8..feee48b 100755 --- a/shogi-server +++ b/shogi-server @@ -38,7 +38,6 @@ require 'getoptlong' require 'thread' require 'timeout' require 'socket' -require 'ping' TCPSocket.do_not_reverse_lookup = true @@ -385,9 +384,10 @@ class Board def initialize @sente_hands = Array::new @gote_hands = Array::new + @history = Hash::new @array = [[], [], [], [], [], [], [], [], [], []] end - attr_accessor :array, :sente_hands, :gote_hands + attr_accessor :array, :sente_hands, :gote_hands, :history def initial @array[1][1] = Piece::new("KY", false) @@ -433,6 +433,13 @@ class Board @array[9][7] = Piece::new("FU", true) end + def have_piece?(hands, name) + p = hands.find { |i| + i.name == name + } + return p + end + def get_piece_from_hands(hands, name) p = hands.find { |i| i.name == name @@ -444,7 +451,6 @@ class Board end def handle_one_move(str) - begin if (str =~ /^([\+\-])(\d)(\d)(\d)(\d)([A-Z]{2})/) p = $1 x0 = $2.to_i @@ -452,18 +458,21 @@ class Board x1 = $4.to_i y1 = $5.to_i name = $6 - - if ((x1 == 0) || (y1 == 0)) - return "illegal" - end elsif (str =~ /^%KACHI/) - return "kachi" + return :kachi elsif (str =~ /^%TORYO/) - return "toryo" + return :toryo else - return "illegal" + return :illegal end - + + if (((x0 == 0) || (y0 == 0)) && # source is not from hand + ((x0 != 0) || (y0 != 0))) + return :illegal + elsif ((x1 == 0) || (y1 == 0)) # destination is out of board + return :illegal + end + if (p == "+") sente = true hands = @sente_hands @@ -471,36 +480,56 @@ class Board sente = false hands = @gote_hands end - if (@array[x1][y1]) - if (@array[x1][y1] == sente) # this is mine - return "illegal" - elsif (@array[x1][y1].name == "OU") - return "outori" - end - hands.push(@array[x1][y1]) - @array[x1][y1] = nil + + ## source check + if ((x0 == 0) && (y0 == 0)) + return :illegal if (! have_piece?(hands, name)) + elsif (! @array[x0][y0]) + return :illegal # no piece + elsif (@array[x0][y0].sente != sente) + return :illegal # this is not mine + elsif (@array[x0][y0].name != name) + return :illegal if (@array[x0][y0].promoted_name != name) # can't promote + end + + ## destination check + if (@array[x1][y1] && + (@array[x1][y1].sente == sente)) # can't capture mine + return :illegal + elsif ((x0 == 0) && (y0 == 0) && @array[x1][y1]) + return :illegal # can't put on existing piece end + if ((x0 == 0) && (y0 == 0)) p = get_piece_from_hands(hands, name) - return "illegal" if (! p) # i don't have this one @array[x1][y1] = p p.sente = sente p.promoted = false else - if (@array[x0][y0] == nil) - return "illegal"; - end if (@array[x0][y0].name != name) # promoted ? - return "illegal" if (@array[x0][y0].promoted_name != name) # can't promote @array[x0][y0].promoted = true end + if (@array[x1][y1]) + if (@array[x1][y1].name == "OU") + return :outori # return board update + end + hands.push(@array[x1][y1]) + hands.sort! {|a, b| + a.name <=> b.name + } + end @array[x1][y1] = @array[x0][y0] @array[x0][y0] = nil end - return "normal" # legal move - rescue - return "illegal" - end + + ## sennichite check + str = to_s + @history[str] = (@history[str] || 0) + 1 + if (@history[str] >= 4) + return :sennichite + end + + return :normal # legal move end def to_s @@ -649,11 +678,16 @@ class Game elsif (str == :timeout) return false # time isn't expired. players aren't swapped. continue game else - move_status = @board.handle_one_move(str) - if (move_status == "illegal") + begin + move_status = @board.handle_one_move(str) + rescue + log_error("handle_one_move raise exception for #{str}") + move_status = :illegal + end + if (move_status == :illegal) @fh.printf("'ILLEGAL_MOVE(%s)\n", str) else - if ((move_status == "normal") || (move_status == "outori")) + if ((move_status == :normal) || (move_status == :outori) || (move_status == :sennichite)) @sente.write_safe(sprintf("%s,T%d\n", str, t)) @gote.write_safe(sprintf("%s,T%d\n", str, t)) @fh.printf("%s\nT%d\n", str, t) @@ -677,14 +711,16 @@ class Game abnormal_win() elsif (status == :timeout) timeout_lose() - elsif (move_status == "illegal") + elsif (move_status == :illegal) illegal_lose() - elsif (move_status == "kachi") + elsif (move_status == :kachi) kachi_win() - elsif (move_status == "toryo") + elsif (move_status == :toryo) toryo_lose() - elsif (move_status == "outori") + elsif (move_status == :outori) outori_win() + elsif (move_status == :sennichite) + sennichite_draw() else finish_flag = false end @@ -719,6 +755,17 @@ class Game end end + def sennichite_draw + @current_player.status = "connected" + @next_player.status = "connected" + @current_player.write_safe("#SENNICHITE\n#DRAW\n") + @next_player.write_safe("#SENNICHITE\n#DRAW\n") + @fh.printf("'summary:sennichite:%s draw:%s draw\n", @current_player.name, @next_player.name) + @monitors.each do |monitor| + monitor.write_safe(sprintf("##[MONITOR][%s] #SENNICHITE\n", @id)) + end + end + def illegal_lose @current_player.status = "connected" @next_player.status = "connected" @@ -801,13 +848,13 @@ class Game @fh.printf("$START_TIME:%s\n", Time::new.strftime("%Y/%m/%d %H:%M:%S")) @fh.print <