ExcludeSacrificeGps500.new,
MakeEven.new,
SortByRateWithRandomness.new(1200, 2400),
- StartGame.new]
+ StartGameWithoutHumans.new]
end
def random_pairing
ExcludeSacrificeGps500.new,
MakeEven.new,
Randomize.new,
- StartGame.new]
+ StartGameWithoutHumans.new]
end
def swiss_pairing
- history = ShogiServer::League::Floodgate::History.factory
return [LogPlayers.new,
ExcludeSacrificeGps500.new,
MakeEven.new,
- Swiss.new(history),
- StartGame.new]
+ Swiss.new,
+ StartGameWithoutHumans.new]
end
def match(players)
def match(players)
# to be implemented
+ log_message("Floodgate: %s" % [self.class.to_s])
end
def include_newbie?(players)
end
end
if str_array.empty?
- log_message("Floodgate: [Players] None is here.")
+ log_message("Floodgate: [Players] Nobody found.")
else
log_message("Floodgate: [Players] %s." % [str_array.join(", ")])
end
class LogPlayers < Pairing
def match(players)
+ super
log_players(players)
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
- log_warning("Floodgate: There should be more than one player: %d" % [players.size])
+ log_warning("Floodgate: There should be more than one player (%d)." % [players.size])
return
end
if players.size.odd?
- log_warning("Floodgate: There are odd players: %d. %s will not be matched." %
+ log_warning("Floodgate: There are odd players (%d). %s will not be matched." %
[players.size, players.last.name])
end
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
- def start_game(p1, p2)
- log_message("Floodgate: BLACK %s; WHITE %s" % [p1.name, p2.name])
- p1.sente = true
- p2.sente = false
- Game.new(p1.game_name, p1, p2)
+ # 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
class Swiss < Pairing
- def initialize(history)
- super()
- @history = history
- end
-
def match(players)
super
- winners = players.find_all {|pl| @history.last_win?(pl.player_id)}
- rest = players - winners
+ if players.size < 3
+ log_message("Floodgate: players are small enough to skip Swiss pairing: %d" % [players.size])
+ return
+ end
+
+ path = ShogiServer::League::Floodgate.history_file_path(players.first.game_name)
+ history = ShogiServer::League::Floodgate::History.factory(path)
+
+ winners = []
+ if history
+ winners = players.find_all {|pl| history.last_win?(pl.player_id)}
+ end
+ rest = players - winners
- log_message("Floodgate: %d winners" % [winners.size])
+ log_message("Floodgate: Ordering %d winners..." % [winners.size])
sbrwr_winners = SortByRateWithRandomness.new(800, 2500)
sbrwr_winners.match(winners, true)
- log_players(winners)
- log_message("Floodgate: and the rest: %d" % [rest.size])
+ log_message("Floodgate: Ordering the rest (%d)..." % [rest.size])
sbrwr_losers = SortByRateWithRandomness.new(200, 400)
sbrwr_losers.match(rest, true)
- log_players(rest)
players.clear
[winners, rest].each do |group|
def match(players)
super
return if players.size.even?
- log_message("Floodgate: there are odd players: %d. Deleting one..." %
+ log_message("Floodgate: There are odd players (%d). Deleting one of them..." %
[players.size])
DeletePlayerAtRandom.new.match(players)
end