+ Starting a buoy game, players are notified a starting game
position with the initial position and moves, instread of a
targeting position.
+ + Players are allowed to start buoy games with specific turns.
+ ex. %%GAME buoy_foo-1500-0 +
2010-08-05 Daigo Moriwaki <daigo at debian dot org>
New commands:
+ %%SETBUOY <game_name> <moves> [count]
Set a new buoy game.
- ex. %%SETBUOYGAME buoy_foo-900-0 +7776FU 10
- ex. %%SETBUOYGAME buoy_foo-1500-0 +7776FU-3334FU
+ ex. %%SETBUOY buoy_foo-900-0 +7776FU 10
+ ex. %%SETBUOY buoy_foo-1500-0 +7776FU-3334FU
- game_name is a valid game name with a prefix "buoy_".
ex. buoy_foo-900-0
- moves are initial moves from the Hirate position to a
@command_name = command_name
@game_name = game_name
@my_sente_str = my_sente_str
+ player.set_sente_from_str(@my_sente_str)
end
def call
end
@player.sente = nil
else
- rival = $league.find_rival(@player, @my_sente_str, @game_name)
+ rival = $league.find_rival(@player, @game_name)
if rival.instance_of?(Symbol)
# An error happened. rival is not a player instance, but an error
# symobl that must be returned to the main routine immediately.
if (@command_name == "GAME")
@player.status = "game_waiting"
@player.game_name = @game_name
- @player.set_sente_from_str(@my_sente_str)
else # challenge
@player.write_safe(sprintf("##[ERROR] can't find rival for %s\n", @game_name))
@player.status = "connected"
@player.write_safe(sprintf("##[SETBUOY] +OK\n"))
log_info("A buoy game was created: %s by %s" % [@game_name, @player.name])
- # if two players, who are not @player, are waiting for a new game, start it
- p1 = $league.get_player("game_waiting", @game_name, true, @player)
- return :continue unless p1
- p2 = $league.get_player("game_waiting", @game_name, false, @player)
- return :continue unless p2
-
+ # if two players are waiting for this buoy game, start it
+ candidates = $league.find_all_players do |player|
+ player.status == "game_waiting" &&
+ player.game_name == @game_name &&
+ player.name != @player.name
+ end
+ if candidates.empty?
+ log_info("No players found for a buoy game. Wait for players: %s" % [@game_name])
+ return :continue
+ end
+ p1 = candidates.first
+ p2 = $league.find_rival(p1, @game_name)
+ if p2.nil?
+ log_info("No opponent found for a buoy game. Wait for the opponent: %s by %s" % [@game_name, p1.name])
+ return :continue
+ elsif p2.instance_of?(Symbol)
+ # An error happened. rival is not a player instance, but an error
+ # symobl that must be returned to the main routine immediately.
+ return p2
+ end
+ # found two players: p1 and p2
+ log_info("Starting a buoy game: %s with %s and %s" % [@game_name, p1.name, p2.name])
buoy.decrement_count(buoy_game)
game = Game::new(@game_name, p1, p2, board)
return :continue
+
rescue WrongMoves => e
@player.write_safe(sprintf("##[ERROR] wrong moves: %s\n", @moves))
log_error "Received wrong moves: %s from %s. [%s]" % [@moves, @player.name, e.message]
@@mutex = Mutex.new
@@time = 0
- # Decide turns of players according to their turn preferences.
+ # Decide an actual turn of each player according to their turn preferences.
# p2 is a rival player of the p1 player.
# p1_sente_string must be "*", "+" or "-".
+ # After this call, the sente value of each player is always true or false, not
+ # nil.
#
def Game.decide_turns(p1, p1_sente_string, p2)
if ((p1_sente_string == "*") && (p2.sente == nil))
# 2. a rival player instance found
# 3. nil if rival not found
#
- def find_rival(player, my_sente_string, game_name)
- case my_sente_string
- when "*" # no preference
+ def find_rival(player, game_name)
+ case player.sente
+ when nil # no preference
if Login.handicapped_game_name?(game_name)
player.write_safe("##[ERROR] Random turn preference is not allowed for handicapped games\n")
return :continue
end
return get_player("game_waiting", game_name, nil, player)
- when "+" # rival must be gote
+ when true # rival must be gote
return get_player("game_waiting", game_name, false, player)
- when "-" # rival must be sente
+ when false # rival must be sente
return get_player("game_waiting", game_name, true, player)
else
write_safe("##[ERROR] bad game option: %s\n" % [my_sente_string])
def initialize
@games = {}
@games["dummy_game_id"] = MockGame.new
+
+ reset_players
+ end
+
+ def reset_players
+ $p1 = MockPlayer.new
+ $p1.name = "p1"
+ $p1.status = "game_waiting"
+ $p1.sente = true
+ $p2 = MockPlayer.new
+ $p2.name = "p2"
+ $p2.status = "game_waiting"
+ $p2.sente = false
end
def games
def get_player(status, game_id, sente, searcher)
if sente == true
- $p1 = MockPlayer.new
- $p1.name = "p1"
return $p1
elsif sente == false
- $p2 = MockPlayer.new
- $p2.name = "p2"
return $p2
elsif sente == nil
return nil
return nil
end
end
+
+ def find_all_players
+ [$p1,$p2].each {|pp| yield pp}
+ end
+
+ def find_rival(player, game_name)
+ case player.sente
+ when nil # no preference
+ return get_player("game_waiting", game_name, nil, player)
+ when true # rival must be gote
+ return get_player("game_waiting", game_name, false, player)
+ when false # rival must be sente
+ return get_player("game_waiting", game_name, true, player)
+ else
+ return :continue
+ end
+ end
end
class BaseTestBuoyCommand < Test::Unit::TestCase
def setup
@p = MockPlayer.new
- $p1 = nil
- $p2 = nil
+ $league = MockLeague.new
delete_buoy_yaml
@buoy = ShogiServer::Buoy.new
cmd = ShogiServer::SetBuoyCommand.new "%%SETBUOY", @p, "buoyhoge-1500-0", "+7776FU", 1
rt = cmd.call
assert :continue, rt
- assert !$p1
- assert !$p2
+ assert $p1.out.empty?
+ assert $p2.out.empty?
assert @buoy.is_new_game?("buoy_hoge-1500-0")
end
cmd = ShogiServer::SetBuoyCommand.new "%%SETBUOY", @p, "buoy_duplicated-1500-0", "+7776FU", 1
rt = cmd.call
assert :continue, rt
- assert !$p1
- assert !$p2
+ assert $p1.out.empty?
+ assert $p2.out.empty?
assert !@buoy.is_new_game?("buoy_duplicated-1500-0")
end
cmd = ShogiServer::SetBuoyCommand.new "%%SETBUOY", @p, "buoy_badmoves-1500-0", "+7776FU+8786FU", 1
rt = cmd.call
assert :continue, rt
- assert !$p1
- assert !$p2
+ assert $p1.out.empty?
+ assert $p2.out.empty?
assert @buoy.is_new_game?("buoy_badmoves-1500-0")
end
cmd = ShogiServer::SetBuoyCommand.new "%%SETBUOY", @p, "buoy_badcounter-1500-0", "+7776FU", 0
rt = cmd.call
assert :continue, rt
- assert !$p1
- assert !$p2
+ assert $p1.out.empty?
+ assert $p2.out.empty?
assert @buoy.is_new_game?("buoy_badcounter-1500-0")
end
end
cmd = ShogiServer::DeleteBuoyCommand.new "%%DELETEBUOY", @p, buoy_game.game_name
rt = cmd.call
assert :continue, rt
- assert !$p1
- assert !$p2
+ assert $p1.out.empty?
+ assert $p2.out.empty?
assert @buoy.is_new_game?(buoy_game.game_name)
end
cmd = ShogiServer::DeleteBuoyCommand.new "%%DELETEBUOY", @p, buoy_game.game_name
rt = cmd.call
assert :continue, rt
- assert !$p1
- assert !$p2
+ assert $p1.out.empty?
+ assert $p2.out.empty?
assert @buoy.is_new_game?(buoy_game.game_name)
end