OSDN Git Service

Enhanced the Buoy feature: Players are allowed to start buoy games with specific...
authordaigo <beatles@users.sourceforge.jp>
Sun, 5 Sep 2010 06:13:44 +0000 (15:13 +0900)
committerDaigo Moriwaki <daigo@debian.org>
Sun, 5 Sep 2010 07:56:27 +0000 (16:56 +0900)
ex. %%GAME buoy_foo-1500-0 +

changelog
shogi_server/command.rb
shogi_server/game.rb
shogi_server/league.rb
test/TC_command.rb

index 6d96ca3..05ee28a 100644 (file)
--- 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 <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
index fe0ddf4..a3b48a7 100644 (file)
@@ -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]
index 5e46e12..232eac4 100644 (file)
@@ -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))
index 5936e79..1207472 100644 (file)
@@ -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])
index fb2e134..f23062b 100644 (file)
@@ -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