datatype Move = C | D; (* Cooperate | Defect *) fun payoff C C = 3 (* payoff move1 move2 is... *) | payoff D C = 5 (* gain to the 1st player *) | payoff C D = 0 (* of player1 does move1 *) | payoff D D = 1; (* and player2 does move2 *) fun invert C = D | invert D = C; (* ------------------------------------------------ *) fun good _ _ = C; (* always cooperate *) fun bad _ _ = D; (* always defect *) fun mad _ (D::_) = D (* mutually *) | mad (D::_) _ = D (* assured *) | mad _ _ = C; (* destruction *) (* ------------------------------------------------ *) fun play frac n p1 p2 = (* do not change play *) let (* play n moves of p1 v. p2 *) val noiseLimit = 0.1; val f = if 0.0 > frac then 0.0 else if frac > noiseLimit then noiseLimit else frac; val t = (rev o explode o (fn s => "1234" ^ s) o Time.toString o Time.now)(); val t1::t2::t3::t4::_ = t; (* randomize... *) val r = Random.rand(ord t1 * ord t2, ord t3 * ord t4); fun jiggle m = if f > Random.randReal r then invert m else m; fun go 0 _ _ score1 score2 = (score1, score2) | go n past1 past2 score1 score2 = let (* NB. past histories, most recent 1st *) val m1' = p1 past1 past2 (* p1's next move *) and m2' = p2 past2 past1; (* p2's next move *) val m1 = jiggle m1' and m2 = jiggle m2'; val s1 = payoff m1 m2 and s2 = payoff m2 m1 in go (n-1) (m1::past1) (m2::past2) (s1+score1) (s2+score2) end(*go n*) in go n [] [] 0 0 end(*play*); val playClean = play 0.0; (* zero noise *) (* Prisoner's dilemma in SML, LA, csse, monash u., .au, *) (* Under GNU GPL, http://www.gnu.org/licenses/gpl.txt *) (* 7/2005 *)