From: daigo Date: Sun, 5 Sep 2010 06:13:44 +0000 (+0900) Subject: Enhanced the Buoy feature: Players are allowed to start buoy games with specific... X-Git-Tag: 20170902~92 X-Git-Url: http://git.osdn.net/view?p=shogi-server%2Fshogi-server.git;a=commitdiff_plain;h=0a1c409fedbbc7061dc32114740ab32d5f76735d Enhanced the Buoy feature: Players are allowed to start buoy games with specific turns. ex. %%GAME buoy_foo-1500-0 + --- diff --git a/changelog b/changelog index 6d96ca3..05ee28a 100644 --- a/changelog +++ b/changelog @@ -6,6 +6,8 @@ + 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 @@ -272,8 +274,8 @@ New commands: + %%SETBUOY [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 diff --git a/shogi_server/command.rb b/shogi_server/command.rb index fe0ddf4..a3b48a7 100644 --- a/shogi_server/command.rb +++ b/shogi_server/command.rb @@ -476,6 +476,7 @@ module ShogiServer @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 @@ -497,7 +498,7 @@ module ShogiServer 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. @@ -543,7 +544,6 @@ module ShogiServer 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" @@ -726,15 +726,32 @@ module ShogiServer @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] diff --git a/shogi_server/game.rb b/shogi_server/game.rb index 5e46e12..232eac4 100644 --- a/shogi_server/game.rb +++ b/shogi_server/game.rb @@ -32,9 +32,11 @@ class Game @@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)) diff --git a/shogi_server/league.rb b/shogi_server/league.rb index 5936e79..1207472 100644 --- a/shogi_server/league.rb +++ b/shogi_server/league.rb @@ -105,17 +105,17 @@ class League # 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]) diff --git a/test/TC_command.rb b/test/TC_command.rb index fb2e134..f23062b 100644 --- a/test/TC_command.rb +++ b/test/TC_command.rb @@ -14,6 +14,19 @@ class MockLeague 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 @@ -38,12 +51,8 @@ class MockLeague 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 @@ -51,6 +60,23 @@ class MockLeague 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 @@ -772,8 +798,7 @@ 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 @@ -830,8 +855,8 @@ class TestSetBuoyCommand < BaseTestBuoyCommand 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 @@ -844,8 +869,8 @@ class TestSetBuoyCommand < BaseTestBuoyCommand 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 @@ -854,8 +879,8 @@ class TestSetBuoyCommand < BaseTestBuoyCommand 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 @@ -864,8 +889,8 @@ class TestSetBuoyCommand < BaseTestBuoyCommand 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 @@ -882,8 +907,8 @@ class TestDeleteBuoyCommand < BaseTestBuoyCommand 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 @@ -893,8 +918,8 @@ class TestDeleteBuoyCommand < BaseTestBuoyCommand 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