require 'socket'
TCPSocket.do_not_reverse_lookup = true
+Thread.abort_on_exception = true
class TCPSocket
end
if (@write_queue.size > Max_Write_Queue_Size)
log_warning(sprintf("write_queue of %s is %d", @name, @write_queue.size))
- return
+ return
end
if (@status == "finished")
comment = array_str.unshift("'*#{$1}")
end
s = @game.handle_one_move(move, self)
- @game.fh.print("#{comment}\n") if comment
+ @game.fh.print("#{comment}\n") if (comment && !s)
return if (s && @protocol == "CSA")
end
when /^%[^%]/, :timeout
@sente_history = Hash::new
@gote_history = Hash::new
@array = [[], [], [], [], [], [], [], [], [], []]
+ @move_count = 0
end
attr_accessor :array, :sente_hands, :gote_hands, :history, :sente_history, :gote_history
+ attr_reader :move_count
def initial
PieceKY::new(self, 1, 1, false)
end
@array[x0][y0].move_to(x1, y1)
end
+ @move_count += 1
return true
end
end
def good_kachi?(sente)
- return false if (checkmated?(sente))
+ if (checkmated?(sente))
+ puts "'NG: Checkmating." if $DEBUG
+ return false
+ end
+
ou = look_for_ou(sente)
- return false if (sente && (ou.y >= 4))
- return false if (! sente && (ou.y <= 6))
-
+ if (sente && (ou.y >= 4))
+ puts "'NG: Black's OU does not enter yet." if $DEBUG
+ return false
+ end
+ if (! sente && (ou.y <= 6))
+ puts "'NG: White's OU does not enter yet." if $DEBUG
+ return false
+ end
+
number = 0
point = 0
point = point + piece.point
end
- return false if (number < 10)
+ if (number < 10)
+ puts "'NG: Piece#[%d] is too small." % [number] if $DEBUG
+ return false
+ end
if (sente)
- return false if (point < 28)
+ if (point < 28)
+ puts "'NG: Black's point#[%d] is too small." % [point] if $DEBUG
+ return false
+ end
else
- return false if (point < 27)
+ if (point < 27)
+ puts "'NG: White's point#[%d] is too small." % [point] if $DEBUG
+ return false
+ end
end
+
+ puts "'Good: Piece#[%d], Point[%d]." % [number, point] if $DEBUG
return true
end
- def handle_one_move(str)
+ def handle_one_move(str, sente)
if (str =~ /^([\+\-])(\d)(\d)(\d)(\d)([A-Z]{2})/)
sg = $1
x0 = $2.to_i
y1 = $5.to_i
name = $6
elsif (str =~ /^%KACHI/)
- if (@sente == @current_player)
- sente = true
- else
- sente = false
- end
if (good_kachi?(sente))
return :kachi_win
else
end
class Game
+ @@mutex = Mutex.new
+ @@time = 0
+
def initialize(game_name, player0, player1)
@monitors = Array::new
@game_name = game_name
@sente.status = "agree_waiting"
@gote.status = "agree_waiting"
+
@id = sprintf("%s+%s+%s+%s+%s",
- LEAGUE.event, @game_name, @sente.name, @gote.name,
- Time::new.strftime("%Y%m%d%H%M%S"))
+ LEAGUE.event, @game_name, @sente.name, @gote.name, issue_current_time)
+ @logfile = @id + ".csa"
LEAGUE.games[@id] = self
-
log_message(sprintf("game created %s", @id))
- @logfile = @id + ".csa"
@board = Board::new
@board.initial
@start_time = nil
finish_flag = true
if (@current_player == player)
@end_time = Time::new
- t = (@end_time - @start_time).ceil
+ t = (@end_time - @start_time).floor
t = Least_Time_Per_Move if (t < Least_Time_Per_Move)
move_status = nil
end
# begin
- move_status = @board.handle_one_move(str)
+ move_status = @board.handle_one_move(str, @sente == @current_player)
# rescue
# log_error("handle_one_move raise exception for #{str}")
# move_status = :illegal
def show()
str0 = <<EOM
BEGIN Game_Summary
-Protocol_Version:1.0
+Protocol_Version:1.1
Protocol_Mode:Server
Format:Shogi 1.0
+Declaration:Jishogi 1.1
Game_ID:#{@id}
Name+:#{@sente.name}
Name-:#{@gote.name}
Current_Turn:#{@current_turn}
END Time
BEGIN Position
-Jishogi_Declaration:1.1
EOM
str1 = <<EOM
def propose_message(sg_flag)
str = <<EOM
BEGIN Game_Summary
-Protocol_Version:1.0
+Protocol_Version:1.1
Protocol_Mode:Server
Format:Shogi 1.0
+Declaration:Jishogi 1.1
Game_ID:#{@id}
Name+:#{@sente.name}
Name-:#{@gote.name}
Least_Time_Per_Move:#{Least_Time_Per_Move}
END Time
BEGIN Position
-Jishogi_Declaration:1.1
P1-KY-KE-GI-KI-OU-KI-GI-KE-KY
P2 * -HI * * * * * -KA *
P3-FU-FU-FU-FU-FU-FU-FU-FU-FU
EOM
return str
end
+
+ private
+
+ def issue_current_time
+ time = Time::new.strftime("%Y%m%d%H%M%S").to_i
+ @@mutex.synchronize do
+ while time <= @@time do
+ time += 1
+ end
+ @@time = time
+ end
+ end
end
def usage
while true
begin
timeout(sec) do
- mutex.lock
- mutex.unlock
+ begin
+ mutex.lock
+ ensure
+ mutex.unlock
+ end
end
sleep(sec)
rescue TimeoutError
def main
$mutex = Mutex::new
Thread::start do
+ Thread.pass
mutex_watchdog($mutex, 10)
end
write_pid_file($options["pid-file"]) if ($options["pid-file"])
- Thread.abort_on_exception = true
server = TCPserver.open(port)
log_message("server started")
while true
Thread::start(server.accept) do |client|
+ Thread.pass
client.sync = true
player = nil
while (str = client.gets_timeout(Login_Time))
client.write_safe(sprintf("username %s is already connected%s", player.name, eol)) if (str.split.length >= 4)
client.close
Thread::exit
+ return
end
end
LEAGUE.add(player)
if (! player)
client.close
Thread::exit
+ return
end
log_message(sprintf("user %s login", player.name))
player.run
if (player.game)
player.game.kill(player)
end
- player.finish
+ player.finish # socket has been closed
LEAGUE.delete(player)
log_message(sprintf("user %s logout", player.name))
ensure