From 1ca7f925267210492221078a97a92db4301b8f67 Mon Sep 17 00:00:00 2001 From: Tim Carey-Smith Date: Thu, 21 Aug 2008 00:57:43 -0700 Subject: [PATCH] Add the N times M foursquare example --- n-times-m-foursquare/lib/player.rb | 62 ++++++++++++++++++++++++++++++ n-times-m-foursquare/lib/round.rb | 34 ++++++++++++++++ n-times-m-foursquare/play.rb | 38 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 n-times-m-foursquare/lib/player.rb create mode 100644 n-times-m-foursquare/lib/round.rb create mode 100755 n-times-m-foursquare/play.rb diff --git a/n-times-m-foursquare/lib/player.rb b/n-times-m-foursquare/lib/player.rb new file mode 100644 index 0000000..3f82734 --- /dev/null +++ b/n-times-m-foursquare/lib/player.rb @@ -0,0 +1,62 @@ +class Player + include Dramatis::Actor + + attr_reader :name + def initialize(name) + @name = name + @rounds = [] + @round_names = [] + @opponents = [] + end + + def join(round, round_name) + @rounds << round + @round_names << round_name + @opponents << [] + end + + def add(round, opponent) + opponents_for(round) << opponent + end + + def serve(round) + # We ignore the possiblity + # of service faults + opponent = choose_for(round) + release(opponent).volley(round, 1) + end + + def volley(round, volleys) + # We ignore serve do-overs + # We ignore out of bound hits + if made_save + # we ignore bad hits + opponent = choose_for(round) + release(opponent).volley(round, volleys + 1) + else + round.failed(self, volleys) + end + end + +private + def made_save + rand < 0.99999 + end + + def index_for(round) + @rounds.index(round) + end + + def round_name_for(round) + @round_names[index_for(round)] + end + + def opponents_for(round) + @opponents[index_for(round)] + end + + def choose_for(round) + o = opponents_for(round) + o[rand(o.size)] + end +end diff --git a/n-times-m-foursquare/lib/round.rb b/n-times-m-foursquare/lib/round.rb new file mode 100644 index 0000000..7f79793 --- /dev/null +++ b/n-times-m-foursquare/lib/round.rb @@ -0,0 +1,34 @@ +class Round + include Dramatis::Actor + + def initialize(name, players) + actor.refuse :finished? + @start_time = Time.now + @name = name + @players = players + puts "START: #{@name} with #{@players.size} players" + @players.each do |player| + player.join(self, @name) + @players.each do |opponent| + next if opponent == player + player.add(self, opponent) + end + end + end + + def play + release(@players[-1]).serve(self) + end + + def failed(loser, volleys) + @end_time = Time.now + @loser = loser + @volleys = volleys + puts "END: #{@name} in #{@end_time - @start_time} seconds" + actor.accept :finished? + end + + def finished? + !!@loser + end +end diff --git a/n-times-m-foursquare/play.rb b/n-times-m-foursquare/play.rb new file mode 100755 index 0000000..9591dba --- /dev/null +++ b/n-times-m-foursquare/play.rb @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby + +$:.unshift File.dirname(__FILE__) + '/../dramatis/lib' +require 'dramatis' +require 'dramatis/actor' +require 'set' + +$:.unshift File.dirname(__FILE__) + '/lib' +require 'round' +require 'player' + +players_count = ARGV.shift.to_i +rounds_count = ARGV.shift.to_i +puts "Running with #{players_count} players, #{rounds_count} rounds" + +players = [] +players_count.times do |i| + players << Player.new("player-#{i}") +end +puts + +rounds = [] +rounds_count.times do |i| + set = Set.new + (rand(30).to_i + 5).times do + set << players[rand(players.size)] + end + rounds << Round.new("round-#{i}", set.to_a) +end + +rounds.each do |r| + r.play +end + +until rounds.all? {|r| r.finished?} + puts "Waiting" + sleep 1 +end