Browse Source

Keyboard driven tournament play with a player list

master
Peter J. Jones 7 years ago
parent
commit
ce971ba9d4

+ 12
- 0
bin/fpd View File

@@ -17,6 +17,8 @@ class Configuration
:no_auth => false,
:board_size => 10,
:log_file => 'fpd.log',
:match => :highest,
:keyboard => false,
}

##############################################################################
@@ -48,6 +50,11 @@ class Configuration

p.on('--tournament', 'Play tournament games') do
options.server = Freeplayd::Servers::Tournament
options.keyboard = true
end

p.on('--match-lowest', 'Winner plays lowest scoring player') do
options.match = :lowest
end

p.on('--stdout', 'Use STDOUT instead of a log file') do
@@ -76,6 +83,11 @@ begin
server.config = config

EventMachine.start_server("0.0.0.0", config.port, config.server)

if config.keyboard
Freeplayd::Keyboard.server = config.server
EventMachine.open_keyboard(Freeplayd::Keyboard)
end
end
rescue RuntimeError => e
$stderr.puts(File.basename($0) + ": ERROR: #{e}")

+ 3
- 0
lib/freeplayd.rb View File

@@ -8,7 +8,10 @@ require('csv')
module Freeplayd
autoload('AI', 'freeplayd/ai')
autoload('Auth', 'freeplayd/auth')
autoload('Client', 'freeplayd/client')
autoload('Game', 'freeplayd/game')
autoload('GUI', 'freeplayd/gui')
autoload('Keyboard', 'freeplayd/keyboard')
autoload('RemotePlayer', 'freeplayd/remote_player')
autoload('Servers', 'freeplayd/server')
autoload('Spaces', 'freeplayd/spaces')

+ 9
- 0
lib/freeplayd/client.rb View File

@@ -0,0 +1,9 @@
class Freeplayd::Client
attr_accessor(:connection, :name, :rank, :games)

def initialize (connection, name)
@connection = connection
@name = name
@rank = @games = 0
end
end

+ 9
- 1
lib/freeplayd/game.rb View File

@@ -29,7 +29,15 @@ class Freeplayd::Game
update_boards(x, y)
stop = game_over?
@score, @live = update_score
@winner = @score.max {|a,b| a.last <=> b.last}.first if stop

if stop
@winner =
if @score[:white] == @score[:black]
:white # White always wins a tie
else
@score.max {|a,b| a.last <=> b.last}.first
end
end
end

##############################################################################

+ 69
- 0
lib/freeplayd/gui.rb View File

@@ -0,0 +1,69 @@
class Freeplayd::GUI < Freeplay::GUI

##############################################################################
def initialize (*args, &block)
super

@client_ui = @container.children
@server_ui = create_server_ui
@container.pack_start(@server_ui, true)

show_server_ui
end

##############################################################################
def board= (board)
super

if @container
@client_ui = @container.children.select do |child|
child != @list
end
end
end

##############################################################################
def show_client_ui
@server_ui.hide
@client_ui.each(&:show)
end

##############################################################################
def show_server_ui
@client_ui.each(&:hide)
@server_ui.show
end

##############################################################################
def add_client (client)
it = @model.append
it[0] = client.name
it[1] = client.rank
it[2] = client.games
end

##############################################################################
def reset_clients (clients)
@model.clear
clients.each {|c| add_client(c)}
end

##############################################################################
private

##############################################################################
def create_server_ui
@model = Gtk::ListStore.new(String, Integer, Integer)
@list = Gtk::TreeView.new(@model)

renderer = Gtk::CellRendererText.new

[
Gtk::TreeViewColumn.new("Player", renderer, :text => 0),
Gtk::TreeViewColumn.new("Games Won", renderer, :text => 1),
Gtk::TreeViewColumn.new("Games Played", renderer, :text => 2),
].each {|c| @list.append_column(c)}

@list
end
end

+ 40
- 0
lib/freeplayd/keyboard.rb View File

@@ -0,0 +1,40 @@
################################################################################
# Control the tournament via the keyboard.
class Freeplayd::Keyboard < EventMachine::Connection

##############################################################################
include(EventMachine::Protocols::LineText2)

##############################################################################
def self.server= (server)
@@server = server
end

##############################################################################
def self.server
@@server
end

##############################################################################
def prompt
$stderr.print("Press [Enter] for next game: ")
end

##############################################################################
def post_init
prompt
end

##############################################################################
def receive_line (keys)
if (@tournament ||= self.class.server.tournament) and
!@tournament.clients.empty?
then
@tournament.change_state
else
$stdout.puts("No clients are ready...")
end

prompt
end
end

+ 14
- 8
lib/freeplayd/servers/tournament.rb View File

@@ -1,30 +1,36 @@
class Freeplayd::Servers::Tournament < Freeplayd::Servers::Base

##############################################################################
def self.tournament
@@tournament rescue nil
end

##############################################################################
def tournament
self.class.tournament
end

##############################################################################
attr_accessor(:playing)

##############################################################################
def authentication_confirmed
full_name = @@auth.full_name(@user_name)
@@tournament ||= Freeplayd::Tournament.new(@@board_size, @@logger)
@@tournament.add_connection(self, full_name)
@@tournament ||= Freeplayd::Tournament.new(@@board_size, @@logger, @@config)
tournament.add_connection(self, full_name)
message("Waiting for a tournament round to begin...")

if @@tournament.game.nil? and @@tournament.clients.size >= 2
@@tournament.start_next_game
end
end

##############################################################################
def unbind
@@tournament.remove_connection(self)
tournament.remove_connection(self)
end

##############################################################################
def move (coordinates)
return player_error("you're not playing!") if !@playing
logger.info("incoming move from #{self.object_id}")
@@tournament.player_moved(self, coordinates)
tournament.player_moved(self, coordinates)
end

##############################################################################

+ 64
- 20
lib/freeplayd/tournament.rb View File

@@ -1,32 +1,28 @@
class Freeplayd::Tournament

##############################################################################
class Client
attr_accessor(:connection, :name, :rank, :games)

def initialize (connection, name)
@connection = connection
@name = name
@rank = @games = 0
end
end

##############################################################################
attr_reader(:logger, :clients, :game)

##############################################################################
def initialize (size, logger)
def initialize (size, logger, config)
@size = size
@logger = logger
@config = config
@clients = []
@game = nil
@random = Random.new
@last_winner = nil
@state = :idle
@random = Random.new

@gui = Freeplayd::GUI.new {EventMachine.stop}
EventMachine.add_periodic_timer(0.01) {@gui.update}
end

##############################################################################
def add_connection (connection, name)
@clients << Client.new(connection, name)
@clients << Freeplayd::Client.new(connection, name)
sort_clients
@gui.reset_clients(@clients)
logger.info("new client: #{name} (#{connection.object_id})")
end

@@ -39,6 +35,37 @@ class Freeplayd::Tournament
end

@clients.delete(client)
@gui.reset_clients(@clients)
@last_winner = nil if @clients.empty?
end

##############################################################################
def change_state
case @state
when :idle
@state = :playing_client_ui
start_next_game
when :playing_client_ui
@state = :playing_server_ui
@gui.show_server_ui
when :playing_server_ui
@state = :playing_client_ui
@gui.show_client_ui
when :game_over
@state = :idle
@gui.show_server_ui
end
end

##############################################################################
def sort_clients
@clients.sort! do |a, b|
if a.rank == b.rank
a.name <=> b.name
else
b.rank <=> a.rank
end
end
end

##############################################################################
@@ -53,7 +80,14 @@ class Freeplayd::Tournament

if available_players.empty?
available_players = @clients.select {|c| c != @last_winner}
available_players = [available_players.sort {|a, b| b.rank <=> a.rank}.first]
available_players = available_players.sort {|a, b| b.rank <=> a.rank}

case @config.match
when :lowest
available_players = [available_players.last]
else
available_players = [available_players.first]
end
end

white = Freeplayd::RemotePlayer.new
@@ -70,6 +104,11 @@ class Freeplayd::Tournament
white.client.connection.game_starting(@game, :white)
black.client.connection.game_starting(@game, :black)

@gui.board = @game.white.board
@gui.players(white.client.name, black.client.name)
@gui.message("Tournament game in progress...")
@gui.show_client_ui

logger.info("telling #{white.client.name} to take first move")
white.client.connection.take_turn(nil, nil)
end
@@ -93,6 +132,9 @@ class Freeplayd::Tournament
logger.info("#{player.client.name} moved")
@game.player_moved(player, x, y)

@gui.move(player.board.player, x, y)
@gui.score(*@game.score.values)

if @game.winner
game_over
else
@@ -114,9 +156,8 @@ class Freeplayd::Tournament

other.connection.message(message)
@last_winner = other

# FIXME: remove this
start_next_game
@state = :game_over
@gui.message("Tournament game aborted.")
end

##############################################################################
@@ -134,7 +175,10 @@ class Freeplayd::Tournament
loser.client.connection.game_over
loser.client.connection.message("You lost to #{winner.client.name}.")

# FIXME: remove this
start_next_game
@state = :game_over
sort_clients
@gui.message("Tournament game complete. #{winner.client.name} Won!")
@gui.live(*@game.live.values)
@gui.reset_clients(@clients)
end
end

Loading…
Cancel
Save