rock_paper_scissors.pl - Rock Paper Scissors co-evolution example for Algorithm::Evolve
This simulation uses StringEvolver.pm as a base class for crossover, random initialization, and mutation. Unlike examples/string_evolver.pl, this is a co-evolving system where fitness is not absolute, but based on a critter's ability to play Rock, Paper, Scissors against the other members of the population.
In co-evolution, population members are chosen for selection and replacement using the
compare method. In our critter class, we override the default
compare method. Our new
compare method uses each string gene as a sequence of Rock, Paper, and Scissors moves. The gene who wins the most turns is the winner. Notice how we pick a random spot in the string genes to start at, and wrap back to the beginning, taking each move exactly once.
At each generation, the total number of Rock, Paper, and Scissors encodings in the population are tallied and printed. If you graph the output in something like gnuplot, you will probably notice that the population cycles between Rock, Paper, and Scissors being the most prevalent move. This is the command in gnuplot I used to view the output from this script:
gnuplot> plot 'output' using :1 title 'Rock' with lines, \ > 'output' using :2 title 'Paper' with lines, \ > 'output' using :3 title 'Scissors' with lines
Notice how (in general) Scissors overtakes Paper which overtakes Rock which overtakes scissors, etc.
In general, it's more interesting to evolve "thinking" strategies for Rock, Paper, Scissors (or any game), than just a fixed sequence of moves. Such strategies include state machines and genetic programming structures. Hopefully, though, this example illustrates the ease with which you could transparently swap in a different type of strategy for this game.