The weeks Ruby quiz involves writing a simple program to play the game "Paper, Rock, Scissors". Soon after the comments started on the quiz, someone submitted this 12 line "cheating" program:
class Cheater < Player
def initialize opponent
Object.const_get(opponent).send :define_method, :choose do
:paper
end
end
def choose
:scissors
end
end
It cheats in that it dynamically modifies its opponent object so that it always returns :paper, making it trivial to beat. While it does cheat, it does show some clever "thinking outside the box" approach to playing Paper, Rock, Scissors.
This reminds me of a story …
A number of years ago, I used to teach C++ in GE’s after hours education program. One of the projects assigned to the class was writing a player for the game of Greed. Greed is a simple dice game where you score points by rolling a set of 5 dice. You can continue to roll as long as you continue to make points on each roll. However, a row that has no point value causes you to lose all the points for a turn, so there is some value in stopping while you are ahead (hence the name Greed).
The game framework handles the dice rolling. All the student’s prgram had to do was decide whether or not to roll again given the the current state of the dice.
As part of the course, I pointed out that the encapsulation and data hiding features of C++ made it difficult to "cheat" by effecting the framework or other player objects. One particular student took this as a challenge and announced that he had a "cheating" player program that stayed within the "rules" setup by the C++ langauge, but yet would always win.
How did he do it? This cheating player would record the state of the seed of the standard library’s random number generator. It would then do trial rolls of the dice until it got a high scoring roll. Then it would reset the random number seed to the value that produced the high scoring roll, and indicate to the game framework that it wanted to roll again. The framework would comply and give the player the high scoring roll that it was setup to do. The cheating player would win the game in a single turn.
The cheat was easily defeated (once the cheat was understood) by using a private random number generator that wasn’t accessible to the player programs. But I learned two things from this exercise: