- Converting characters for comments in moves caused an error. This
issue has been fixed.
- If a player moves in the opponent's turn, it is illegal. But the
current CSA protocol does not clearly define a way to tell so to
the players. This shogi-server internally keeps such a move in a
buffer and replay it when the player of the move gets his/her
turn.
+2008-03-24 Daigo Moriwaki <daigo at debian dot org>
+
+ * [shogi-server]
+ - Converting characters for comments in moves caused an error. This
+ issue has been fixed.
+ - If a player moves in the opponent's turn, it is illegal. But the
+ current CSA protocol does not clearly define a way to tell so to
+ the players. This shogi-server internally keeps such a move in a
+ buffer and replay it when the player of the move gets his/her
+ turn.
+
2008-03-16 Daigo Moriwaki <daigo at debian dot org>
* [shogi-server]
2008-03-16 Daigo Moriwaki <daigo at debian dot org>
* [shogi-server]
@game_name = ""
@mytime = 0 # set in start method also
@sente = nil
@game_name = ""
@mytime = 0 # set in start method also
@sente = nil
@main_thread = Thread::current
@main_thread = Thread::current
+ @mutex_write_guard = Mutex.new
end
attr_accessor :socket, :status
attr_accessor :protocol, :eol, :game, :mytime, :game_name, :sente
attr_accessor :main_thread
end
attr_accessor :socket, :status
attr_accessor :protocol, :eol, :game, :mytime, :game_name, :sente
attr_accessor :main_thread
+ attr_reader :socket_buffer
def kill
log_message(sprintf("user %s killed", @name))
def kill
log_message(sprintf("user %s killed", @name))
- begin
- @socket.write(str)
- rescue Exception => ex
- log_error("Failed to send a message to #{@name}.")
- log_error("#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}")
- # TODO close
+ @mutex_write_guard.synchronize do
+ begin
+ if r = select(nil, [@socket], nil, 20)
+ r[1].first.write(str)
+ else
+ log_error("Sending a message to #{@name} timed up.")
+ end
+ rescue Exception => ex
+ log_error("Failed to send a message to #{@name}.")
+ log_error("#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}")
+ # TODO close
+ end
end
def run(csa_1st_str=nil)
end
def run(csa_1st_str=nil)
- while (csa_1st_str || (str = gets_safe(@socket, Default_Timeout)))
+ while (csa_1st_str ||
+ str = @socket_buffer.shift || gets_safe(@socket, Default_Timeout))
+ $mutex.lock
+ log_message(str) if $DEBUG
if (csa_1st_str)
str = csa_1st_str
if (csa_1st_str)
str = csa_1st_str
return
end
str.chomp! if (str.class == String) # may be strip! ?
return
end
str.chomp! if (str.class == String) # may be strip! ?
- log_message(str) if $DEBUG
case str
when ""
# Application-level protocol for Keep-Alive
case str
when ""
# Application-level protocol for Keep-Alive
comment = array_str.unshift("'*#{$1.toeuc}")
end
s = @game.handle_one_move(move, self)
comment = array_str.unshift("'*#{$1.toeuc}")
end
s = @game.handle_one_move(move, self)
- @game.fh.print("#{comment}\n") if (comment && !s)
+ @game.fh.print("#{Kconv.toeuc(comment.first)}\n") if (comment && comment.first && !s)
return if (s && @protocol == LoginCSA::PROTOCOL)
end
when /^%[^%]/, :timeout
return if (s && @protocol == LoginCSA::PROTOCOL)
end
when /^%[^%]/, :timeout
+ unless @socket_buffer.empty?
+ sleep 10
+ end
end # enf of while
end # def run
end # class
end # enf of while
end # def run
end # class
else
@sente, @gote = player1, player0
end
else
@sente, @gote = player1, player0
end
+ @sente.socket_buffer.clear
+ @gote.socket_buffer.clear
@current_player, @next_player = @sente, @gote
@sente.game = self
@gote.game = self
@current_player, @next_player = @sente, @gote
@sente.game = self
@gote.game = self
LEAGUE.games.delete(@id)
end
LEAGUE.games.delete(@id)
end
def handle_one_move(str, player)
def handle_one_move(str, player)
- return nil unless @current_player == player
+ unless @current_player == player
+ @fh.puts("'Skipped %s" % [str])
+ log_warning("Skipped a move [%s] scince it is not %s 's turn." %
+ [str, player.name])
+ player.socket_buffer.unshift(str)
+ Thread.pass
+ return nil
+ end
finish_flag = true
@end_time = Time::new
finish_flag = true
@end_time = Time::new
@fh.printf("'ILLEGAL_MOVE(%s)\n", str)
else
if [:normal, :outori, :sennichite, :oute_sennichite_sente_lose, :oute_sennichite_gote_lose].include?(move_status)
@fh.printf("'ILLEGAL_MOVE(%s)\n", str)
else
if [:normal, :outori, :sennichite, :oute_sennichite_sente_lose, :oute_sennichite_gote_lose].include?(move_status)
+ # Thinking time includes network traffic
@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)
@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)