OSDN Git Service

- shogi_server/pairing.rb: Added a new class: StartGameWithoutHumans.
authorbeatles <beatles@b8c68f68-1e22-0410-b08e-880e1f8202b4>
Sat, 26 Dec 2009 01:40:16 +0000 (01:40 +0000)
committerbeatles <beatles@b8c68f68-1e22-0410-b08e-880e1f8202b4>
Sat, 26 Dec 2009 01:40:16 +0000 (01:40 +0000)
This tries to make pairs trying to avoid a human-human match. This is now enabled instread of the previous class: StartGame.

changelog
shogi_server/pairing.rb
test/TC_ALL.rb
test/TC_floodgate.rb
test/TC_pairing.rb [new file with mode: 0644]

index b0b0dab..61140dc 100644 (file)
--- a/changelog
+++ b/changelog
@@ -5,6 +5,10 @@
            is_computer?. 
            A human player is recommened to use a name ending with '_human'.  
            ex. 'hoge_human', 'hoge_human@p1'
            is_computer?. 
            A human player is recommened to use a name ending with '_human'.  
            ex. 'hoge_human', 'hoge_human@p1'
+         - shogi_server/pairing.rb: Added a new class:
+           StartGameWithoutHumans, which tries to make pairs trying to
+           avoid a human-human match. This is now enabled instread of the
+           previous class: StartGame.
 
 2009-12-04 Daigo Moriwaki <daigo at debian dot org>
 
 
 2009-12-04 Daigo Moriwaki <daigo at debian dot org>
 
index 2f5c616..4e0b6d6 100644 (file)
@@ -33,7 +33,7 @@ module ShogiServer
                 ExcludeSacrificeGps500.new,
                 MakeEven.new,
                 SortByRateWithRandomness.new(1200, 2400),
                 ExcludeSacrificeGps500.new,
                 MakeEven.new,
                 SortByRateWithRandomness.new(1200, 2400),
-                StartGame.new]
+                StartGameWithoutHumans.new]
       end
 
       def random_pairing
       end
 
       def random_pairing
@@ -41,7 +41,7 @@ module ShogiServer
                 ExcludeSacrificeGps500.new,
                 MakeEven.new,
                 Randomize.new,
                 ExcludeSacrificeGps500.new,
                 MakeEven.new,
                 Randomize.new,
-                StartGame.new]
+                StartGameWithoutHumans.new]
       end
 
       def swiss_pairing
       end
 
       def swiss_pairing
@@ -50,7 +50,7 @@ module ShogiServer
                 ExcludeSacrificeGps500.new,
                 MakeEven.new,
                 Swiss.new(history),
                 ExcludeSacrificeGps500.new,
                 MakeEven.new,
                 Swiss.new(history),
-                StartGame.new]
+                StartGameWithoutHumans.new]
       end
 
       def match(players)
       end
 
       def match(players)
@@ -105,7 +105,23 @@ module ShogiServer
     end
   end
 
     end
   end
 
-  class StartGame < Pairing
+  class AbstractStartGame < Pairing
+    def start_game(p1, p2)
+      log_message("Floodgate: Starting a game: BLACK %s vs WHITE %s" % [p1.name, p2.name])
+      p1.sente = true
+      p2.sente = false
+      board = Board.new
+      board.initial
+      Game.new(p1.game_name, p1, p2, board)
+    end
+
+    def start_game_shuffle(pair)
+      pair.shuffle!
+      start_game(pair.first, pair.last)
+    end
+  end
+
+  class StartGame < AbstractStartGame
     def match(players)
       super
       if players.size < 2
     def match(players)
       super
       if players.size < 2
@@ -120,18 +136,79 @@ module ShogiServer
       log_players(players)
       while (players.size >= 2) do
         pair = players.shift(2)
       log_players(players)
       while (players.size >= 2) do
         pair = players.shift(2)
-        pair.shuffle!
-        start_game(pair.first, pair.last)
+        start_game_shuffle(pair)
       end
     end
       end
     end
+  end
 
 
-    def start_game(p1, p2)
-      log_message("Floodgate: Starting a game: BLACK %s vs WHITE %s" % [p1.name, p2.name])
-      p1.sente = true
-      p2.sente = false
-      board = Board.new
-      board.initial
-      Game.new(p1.game_name, p1, p2, board)
+  # This tries to avoid a human-human match
+  #
+  class StartGameWithoutHumans < AbstractStartGame
+    def match(players)
+      super
+      log_players(players)
+      if players.size < 2
+        log_warning("Floodgate: There should be more than one player (%d)." % [players.size])
+        return
+      elsif players.size == 2
+        start_game_shuffle(players)
+        return
+      end
+
+      loop do 
+        humans = get_human_indexes(players)
+        log_message("Floodgate: There are (still) %d humans." % [humans.size])
+        break if humans.size < 2
+
+        pairing_possible = false
+        for i in 0..(humans.size-2)  # -2
+          next if humans[i].odd?
+          if humans[i]+1 == humans[i+1]
+            pairing_possible = i
+            break
+          end
+        end
+        unless pairing_possible
+          log_message("Floodgate: No possible human-human match found")
+          break
+        end
+
+        current_index = pairing_possible
+        j = (current_index == 0 ? current_index : current_index-1)
+        while j < players.size
+          break if players[j].is_computer?
+          j += 1
+        end
+
+        pairing_indexes = []
+        if j == players.size 
+          # no computer player found
+          pairing_indexes << current_index << current_index+1
+        else
+          # a comupter player found
+          pairing_indexes << current_index << j
+        end
+
+        pair = []
+        pair << players.delete_at(pairing_indexes.max)
+        pair << players.delete_at(pairing_indexes.min)
+        start_game_shuffle(pair)
+      end # loop
+
+      while (players.size >= 2) do
+        pair = players.shift(2)
+        start_game_shuffle(pair)
+      end
+    end
+
+    private
+
+    def get_human_indexes(players)
+      ret = []
+      for i in 0..(players.size-1)
+        ret << i if players[i].is_human?
+      end
+      return ret
     end
   end
 
     end
   end
 
index 43282af..58fd58a 100644 (file)
@@ -15,6 +15,7 @@ require 'TC_league'
 require 'TC_login'
 require 'TC_not_sennichite'
 require 'TC_oute_sennichite'
 require 'TC_login'
 require 'TC_not_sennichite'
 require 'TC_oute_sennichite'
+require 'TC_pairing'
 require 'TC_player'
 require 'TC_rating'
 require 'TC_uchifuzume'
 require 'TC_player'
 require 'TC_rating'
 require 'TC_uchifuzume'
index be5b3af..c019a68 100644 (file)
@@ -84,66 +84,6 @@ class TestPairing < Test::Unit::TestCase
   end
 end
 
   end
 end
 
-class TestStartGame < Test::Unit::TestCase
-  def setup
-    @pairing= ShogiServer::StartGame.new
-    $called = 0
-    def @pairing.start_game(p1,p2)
-      $called += 1
-    end
-    @a = ShogiServer::BasicPlayer.new
-    @a.name = "a"
-    @a.win  = 1
-    @a.loss = 2
-    @a.rate = 0
-    @b = ShogiServer::BasicPlayer.new
-    @b.name = "b"
-    @b.win  = 10
-    @b.loss = 20
-    @b.rate = 1500
-    @c = ShogiServer::BasicPlayer.new
-    @c.name = "c"
-    @c.win  = 100
-    @c.loss = 200
-    @c.rate = 1000
-    @d = ShogiServer::BasicPlayer.new
-    @d.name = "d"
-    @d.win  = 1000
-    @d.loss = 2000
-    @d.rate = 2000
-  end
-
-  def test_match_two_players
-    players = [@a,@b]
-    @pairing.match(players)
-    assert_equal(1, $called)
-  end
-
-  def test_match_one_player
-    players = [@a]
-    @pairing.match(players)
-    assert_equal(0, $called)
-  end
-
-  def test_match_zero_player
-    players = []
-    @pairing.match(players)
-    assert_equal(0, $called)
-  end
-
-  def test_match_three_players
-    players = [@a,@b,@c]
-    @pairing.match(players)
-    assert_equal(1, $called)
-  end
-
-  def test_match_four_players
-    players = [@a,@b,@c,@d]
-    @pairing.match(players)
-    assert_equal(2, $called)
-  end
-end
-
 class TestDeleteMostPlayingPlayer < Test::Unit::TestCase
   def setup
     @pairing= ShogiServer::DeleteMostPlayingPlayer.new
 class TestDeleteMostPlayingPlayer < Test::Unit::TestCase
   def setup
     @pairing= ShogiServer::DeleteMostPlayingPlayer.new
diff --git a/test/TC_pairing.rb b/test/TC_pairing.rb
new file mode 100644 (file)
index 0000000..77f0522
--- /dev/null
@@ -0,0 +1,274 @@
+$:.unshift File.join(File.dirname(__FILE__), "..")
+require 'test/unit'
+require 'shogi_server'
+require 'shogi_server/player'
+require 'shogi_server/pairing'
+
+class MockLogger
+  def debug(str)
+  end
+  def info(str)
+    #puts str
+  end
+  def warn(str)
+  end
+  def error(str)
+  end
+end
+
+$logger = MockLogger.new
+def log_message(msg)
+  $logger.info(msg)
+end
+
+def log_warning(msg)
+  $logger.warn(msg)
+end
+
+def same_pair?(a, b)
+  unless a.size == 2 && b.size == 2
+    return false
+  end
+
+  return true if [a.first, a.last] == b || [a.last, a.first] == b
+end
+
+class TestStartGame < Test::Unit::TestCase
+  def setup
+    @pairing= ShogiServer::StartGame.new
+    $called = 0
+    def @pairing.start_game(p1,p2)
+      $called += 1
+    end
+    @a = ShogiServer::BasicPlayer.new
+    @a.name = "a"
+    @a.win  = 1
+    @a.loss = 2
+    @a.rate = 0
+    @b = ShogiServer::BasicPlayer.new
+    @b.name = "b"
+    @b.win  = 10
+    @b.loss = 20
+    @b.rate = 1500
+    @c = ShogiServer::BasicPlayer.new
+    @c.name = "c"
+    @c.win  = 100
+    @c.loss = 200
+    @c.rate = 1000
+    @d = ShogiServer::BasicPlayer.new
+    @d.name = "d"
+    @d.win  = 1000
+    @d.loss = 2000
+    @d.rate = 2000
+  end
+
+  def test_match_two_players
+    players = [@a,@b]
+    @pairing.match(players)
+    assert_equal(1, $called)
+  end
+
+  def test_match_one_player
+    players = [@a]
+    @pairing.match(players)
+    assert_equal(0, $called)
+  end
+
+  def test_match_zero_player
+    players = []
+    @pairing.match(players)
+    assert_equal(0, $called)
+  end
+
+  def test_match_three_players
+    players = [@a,@b,@c]
+    @pairing.match(players)
+    assert_equal(1, $called)
+  end
+
+  def test_match_four_players
+    players = [@a,@b,@c,@d]
+    @pairing.match(players)
+    assert_equal(2, $called)
+  end
+end
+
+class TestStartGameWithoutHumans < Test::Unit::TestCase
+  def setup
+    @pairing= ShogiServer::StartGameWithoutHumans.new
+    $paired = []
+    $called = 0
+    def @pairing.start_game(p1,p2)
+      $called += 1
+      $paired << [p1,p2]
+    end
+    @a = ShogiServer::BasicPlayer.new
+    @a.name = "a"
+    @a.win  = 1
+    @a.loss = 2
+    @a.rate = 0
+    @b = ShogiServer::BasicPlayer.new
+    @b.name = "b"
+    @b.win  = 10
+    @b.loss = 20
+    @b.rate = 1500
+    @c = ShogiServer::BasicPlayer.new
+    @c.name = "c"
+    @c.win  = 100
+    @c.loss = 200
+    @c.rate = 1000
+    @d = ShogiServer::BasicPlayer.new
+    @d.name = "d"
+    @d.win  = 1000
+    @d.loss = 2000
+    @d.rate = 2000
+  end
+
+  def test_match_one_player
+    players = [@a]
+    @pairing.match(players)
+    assert_equal(0, $called)
+  end
+
+  def test_match_one_player_human
+    @a.name += "_human"
+    players = [@a]
+    @pairing.match(players)
+    assert_equal(0, $called)
+  end
+
+  def test_match_two_players
+    players = [@a,@b]
+    @pairing.match(players)
+    assert_equal(1, $called)
+  end
+
+  def test_match_two_players_humans
+    @a.name += "_human"
+    @b.name += "_human"
+    players = [@a,@b]
+    @pairing.match(players)
+    assert_equal(1, $called)
+  end
+
+  def test_match_zero_player
+    players = []
+    @pairing.match(players)
+    assert_equal(0, $called)
+  end
+
+  def test_match_three_players
+    players = [@a,@b,@c]
+    @pairing.match(players)
+    assert_equal(1, $called)
+  end
+
+  def test_match_three_players_a_human
+    @a.name += "_human"
+    players = [@a,@b,@c]
+    @pairing.match(players)
+    assert_equal(1, $called)
+    assert_equal(1, players.size)
+    assert_equal(@c, players[0])
+  end
+
+  def test_match_three_players_b_human
+    @b.name += "_human"
+    players = [@a,@b,@c]
+    @pairing.match(players)
+    assert_equal(1, $called)
+    assert_equal(1, players.size)
+    assert_equal(@c, players[0])
+  end
+
+  def test_match_three_players_c_human
+    @c.name += "_human"
+    players = [@a,@b,@c]
+    @pairing.match(players)
+    assert_equal(1, $called)
+    assert_equal(1, players.size)
+    assert_equal(@c, players[0])
+  end
+
+  def test_match_three_players_ab_human
+    @a.name += "_human"
+    @b.name += "_human"
+    players = [@a,@b,@c]
+    @pairing.match(players)
+    assert_equal(1, $called)
+    assert_equal(1, players.size)
+    assert_equal(@b, players[0])
+  end
+
+  def test_match_three_players_bc_human
+    @b.name += "_human"
+    @c.name += "_human"
+    players = [@a,@b,@c]
+    @pairing.match(players)
+    assert_equal(1, $called)
+    assert_equal(1, players.size)
+    assert_equal(@c, players[0])
+  end
+
+  def test_match_four_players
+    players = [@a,@b,@c,@d]
+    @pairing.match(players)
+    assert_equal(2, $called)
+  end
+
+  def test_match_four_players_ab_human
+    @a.name += "_human"
+    @b.name += "_human"
+    players = [@a,@b,@c,@d]
+    @pairing.match(players)
+    assert_equal(2, $paired.size)
+    assert(same_pair?([@a,@c], $paired[0]))
+    assert(same_pair?([@b,@d], $paired[1]))
+  end
+
+  def test_match_four_players_bc_human
+    @b.name += "_human"
+    @c.name += "_human"
+    players = [@a,@b,@c,@d]
+    @pairing.match(players)
+    assert_equal(2, $paired.size)
+    assert(same_pair?([@a,@b], $paired[0]))
+    assert(same_pair?([@c,@d], $paired[1]))
+  end
+
+  def test_match_four_players_abc_human
+    @a.name += "_human"
+    @b.name += "_human"
+    @c.name += "_human"
+    players = [@a,@b,@c,@d]
+    @pairing.match(players)
+    assert_equal(2, $paired.size)
+    assert(same_pair?([@a,@d], $paired[0]))
+    assert(same_pair?([@b,@c], $paired[1]))
+  end
+
+  def test_match_four_players_bcd_human
+    @b.name += "_human"
+    @c.name += "_human"
+    @d.name += "_human"
+    players = [@a,@b,@c,@d]
+    @pairing.match(players)
+    assert_equal(2, $paired.size)
+    assert(same_pair?([@a,@b], $paired[0]))
+    assert(same_pair?([@c,@d], $paired[1]))
+  end
+
+  def test_match_four_players_abcd_human
+    @a.name += "_human"
+    @b.name += "_human"
+    @c.name += "_human"
+    @d.name += "_human"
+    players = [@a,@b,@c,@d]
+    @pairing.match(players)
+    assert_equal(2, $paired.size)
+    assert(same_pair?([@a,@b], $paired[0]))
+    assert(same_pair?([@c,@d], $paired[1]))
+  end
+end
+
+