From: Harry Ohlsen Date: 2002-11-21T08:25:26+09:00 Subject: Sydney Ruby users' group meeting tonight! --------------Boundary-00=_6EEW30DI0CKKVQVYLW7W Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi People, Well, I've been very slack ... as usual, some are saying :-). I've been=20 studying for exams, so my mind's been elsewhere recently. I went to the trouble of organising a separate mailing list earlier this = week,=20 waited a while to give people a chance to subscribe and then forgot to se= nd a=20 reminder to it !! Anyway, tonight is the monthly meeting. As usual, it's upstairs at the=20 Woolloomooloo Bay Hotel at 6pm. Martin Stannard made the suggestion that we could set up a simple program= ming=20 problem and discuss how different people went about attacking it. Since = I've=20 left this so late, it's probably not going to be much use for tonight, bu= t=20 I've attached some code and a URL at the end, if people feel like having = a=20 go. My thought was that we could use the things that were discussed at the=20 conference earlier this month as a starting point. Things like FreeRIDE,= =20 TaskMaster, Perl idioms in Ruby, NARF, Parrot, web scripting using=20 continuations, YAML. Also, Martin said that if we can't find anything else to discuss, he'll g= o=20 into some of the details of his horse genealogy system. I'm not sure whether I'll make it this month due to study. If not, I'll = see=20 you all at the next meeting. At least I won't get drunk and ask again what weak references are used fo= r :-) As promised, here's the URL for the problem Martin suggested ... http://www.cs.ualberta.ca/~darse/rsbpc.html It's a roshambo (ie, "paper, rock, scissors") game where you write your o= wn=20 player and compete against others. The attached code is a Ruby=20 implementation that Martin wrote. Cheers, Harry O. --------------Boundary-00=_6EEW30DI0CKKVQVYLW7W Content-Type: text/x-c++src; charset="us-ascii"; name="roshambo.rb" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="roshambo.rb" $PossibleMoves = %w{rock paper scissors} $Rock = 0 $Paper = 1 $Scissors = 2 $Round = 0 def biased_roshambo(prob_rock, prob_paper) throw = rand() return $Rock if throw < prob_rock return $Paper if throw < prob_rock + prob_paper $Scissors end class Player attr_reader :history, :currentMove, :name attr_accessor :totalWins, :rounds def initialize clear @totalWins = 0 @rounds = 0 @name = self.class.to_s end def clear @history = [] @currentMove = nil end def move(opponent) @rounds += 1.0 @currentMove = make_move(opponent) end def record_move @history.push(@currentMove) end end class RockPlayer < Player def make_move(opponent) $Rock end end class RandPlayer < Player def make_move(opponent) rand($PossibleMoves.size) end end class R226Player < Player def make_move(opponent) biased_roshambo(0.2, 0.2) end end class RotatePlayer < Player def make_move(opponent) return rand(3) if @history.last.nil? (@history.last + 1).modulo(3) end end class CopyPlayer < Player def make_move(opponent) return rand(3) if !opponent.history.last (opponent.history.last + 1).modulo(3) end end class SwitchPlayer < Player def make_move(opponent) return rand(3) if @history.last.nil? return biased_roshambo(0.0, 0.5) if history.last == $Rock return biased_roshambo(0.5, 0.0) if history.last == $Paper return biased_roshambo(0.5, 0.5) end end class FreqPlayer < Player def make_move(opponent) i, r, p, s = 0, 0, 0, 0 $Round.times do |t| case opponent.history[t] when $Rock then r += 1 when $Paper then p += 1 when $Scissors then s += 1 end end return $Paper if r > p && r > s return $Scissors if p > s return $Rock end end class Freq2Player < Player def initialize super @i, @r, @p, @s = 0, 0, 0, 0 end def make_move(opponent) if !opponent.history.last.nil? opp_last = opponent.history.last case opponent.history.last when $Rock then @r += 1 when $Paper then @p += 1 when $Scissors then @s += 1 end end return $Paper if @r > @p && @r > @s return $Scissors if @p > @s return $Rock end end class SwitchALotPlayer < Player def make_move(opponent) return rand(3) if @history.last.nil? return biased_roshambo(0.12, 0.44) if @history.last == $Rock return biased_roshambo(0.44, 0.12) if @history.last == $Paper return biased_roshambo(0.44, 0.44) if @history.last == $Scissors end end $Players = [RockPlayer.new, RandPlayer.new, R226Player.new, CopyPlayer.new, RotatePlayer.new, SwitchPlayer.new, FreqPlayer.new, Freq2Player.new, SwitchALotPlayer.new, HarryO.new] class Tournament def run $Players.each do |p1| $Players.reverse.each do |p2| if p1 != p2 battle(p1, p2, 1000) end end end $Players.sort! { |p1, p2| p2.totalWins <=> p1.totalWins } puts "-----------------------------------------" $Players.each do |p| print "#{p.name.ljust(20)} #{p.totalWins.to_s.rjust(6)}" puts " #{p.totalWins/p.rounds*100}" end end def winner(p1, p2) return "tie" if p1 == p2 return "p1" if p1 == $Rock && p2 == $Scissors return "p2" if p2 == $Rock && p1 == $Scissors return "p1" if p1 == $Paper && p2 == $Rock return "p2" if p2 == $Paper && p1 == $Rock return "p1" if p1 == $Scissors && p2 == $Paper return "p2" if p2 == $Scissors && p1 == $Paper end def do_round(p1, p2) victor = winner(p1.move(p2), p2.move(p1)) p1.record_move p2.record_move victor end def battle(p1, p2, rounds) puts "Battle between #{p1.name} and #{p2.name}" p1wins = 0 p2wins = 0 p1.clear p2.clear rounds.times do |t| victor = do_round(p1, p2) case victor when 'p1' p1wins += 1 p1.totalWins += 1 when 'p2' then p2wins += 1 p2.totalWins += 1 end $Round = t end puts "#{p1.name} won: [#{p1wins}] #{p2.name} won: [#{p2wins}]" end end t = Tournament.new t.run --------------Boundary-00=_6EEW30DI0CKKVQVYLW7W--