Skip to content

Instantly share code, notes, and snippets.

@rob-mcgrail
Created December 18, 2011 12:37
Show Gist options
  • Save rob-mcgrail/1493273 to your computer and use it in GitHub Desktop.
Save rob-mcgrail/1493273 to your computer and use it in GitHub Desktop.
iterative pd
start_time = Time.now
STDOUT.sync = true
$running = true
$generationcount = 0
def clear
print "\e[2J"; print "\e[0;0f"
end
$population = []
$payoffs = {
:coop => 10,
:uncoop => 1,
:exploited => -6,
:exploitee => 5,
}
$params = {
:elite_births => 1,
:middle_births => 0,
:weak_births => 0,
:generation => 70,
:start_score => 10,
:iterations => 100000000,
:seeds => {'Angel' => 1000, 'Evil' => 10000, 'Vindictive' => 1000}
}
class Player
attr_reader :name, :score
def initialize
@name = nil
@score = $params[:start_score]
@last = nil
end
def to_s
self.class.name.to_s + ' ' + @score.to_s
end
def play
:c
end
def outcome(i, othermove, othername)
@score += i
@last = othermove
end
end
class Evil < Player
def initialize
super
@name = "Evil-#{self.object_id}"
end
def play
:d
end
end
class Angel < Player
def initialize
super
@name = "Angel-#{self.object_id}"
end
end
class Vindictive < Player
def initialize
super
@name = "Vindictive-#{self.object_id}"
end
def play
if @last == :d
:d
else
:c
end
end
end
def seed_gameset(i, classname)
i.times do
$population << Kernel.const_get(classname).new
end
end
def matchup(p1, p2)
if p1.play == :c and p2.play == :c
# puts 'cooperation!'; puts
p1.outcome($payoffs[:coop], :c, p2.name)
p2.outcome($payoffs[:coop], :c, p1.name)
elsif p1.play == :c and p2.play == :d
# puts "#{p1.class.name} exploited by a #{p2.class.name}\n\n"
p1.outcome($payoffs[:exploited], :d, p1.name)
p2.outcome($payoffs[:exploitee], :c, p2.name)
elsif p1.play == :d and p2.play == :c
# puts "#{p2.class.name} exploited by a #{p1.class.name}\n\n"
p1.outcome($payoffs[:exploitee], :c, p1.name)
p2.outcome($payoffs[:exploited], :d, p2.name)
else p1.play == :d and p2.play == :d
# puts 'D E F E C T I O N'; puts
p1.outcome($payoffs[:uncoop], :d, p1.name)
p2.outcome($payoffs[:uncoop], :d, p2.name)
end
end
def cull_dead
$population.each do |p|
$population.delete p if p.score <= 0
end
end
def new_generation
$generationcount +=1
i = $population.length/3
$population.sort! {|a,b| b.score <=> a.score}
elite = $population[0..(i-1)]
middle = $population[i..(i*2)-1]
weak = $population[(i*2)..(i*3)-1]
$population = []
elite.each do |p|
seed_gameset($params[:elite_births], p.class.name)
end
middle.each do |p|
seed_gameset($params[:middle_births], p.class.name)
end
weak.each do |p|
seed_gameset($params[:weak_births], p.class.name)
end
end
def run
$gamecount = 0
$iterations = 0
$params[:iterations].times do
$population.shuffle!
pop = $population.length
if pop <= 1
$running = nil
break
end
a = 0
b = (pop/2)-1
pop = pop/2
pop.times do
matchup($population[a], $population[b])
$gamecount +=1
a+=1; b+=1
end
$iterations+=1
cull_dead
if $population.length <= 1
$running = nil
break
end
if ($iterations%$params[:generation]) == 0
new_generation
end
end
end
def score
if $population.length <= 1
clear
puts 'Everyone is dead'
else
scores = {}
$population.each do |player|
if scores[player.class.name]
scores[player.class.name] += player.score
else
scores[player.class.name] = 0
end
end
clear
print "Game #{$gamecount}\n\nGeneration #{$generationcount}\n\n"
puts "\n\n---------------------------------------------------"
scores.each do |k,v|
puts "\n#{ObjectSpace.each_object(Kernel.const_get(k)){}} #{k}s (Score #{v})"
end
end
end
$params[:seeds].each do |k,v|
seed_gameset v, k
end
threads = []
threads << Thread.new do
while $running do
score
sleep(2)
end
score
end
threads << Thread.new do
run
$running = nil
end
threads.each {|t| t.join}
puts "\n\nI took #{Time.at(Time.now - start_time).gmtime.strftime('%M:%S')}\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment