blob: c81e90cd29644fa317b9271a83efe40c9c7993b0 (
plain) (
tree)
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; OVERVIEW:
;;
;;
;; The PLAY-LOOP procedure takes as its arguments two prisoner's
;; dilemma strategies, and plays an iterated game of approximately
;; one hundred rounds. A strategy is a procedure that takes
;; two arguments: a history of the player's previous plays and
;; a history of the other player's previous plays. A history consists
;; of a sentence of C's and D's. Likewise, a strategy procedure
;; returns either the word C (for "cooperate") or D ("defect").
;; We also need a way to find out the player's scores; GET-SCORES
;; takes two histories and computes the net score for one player.
;;
;; Note that we are inventing various types of objects: strategies,
;; histories, etc. Each type of thing has certain specified
;; properties. For example, a history is a sentence with zero or
;; more words, each of which is a C or D. To help us use these
;; objects, we write procedures that let us forget the details and
;; think about things in terms of histories and rounds, not in terms
;; of sentences and words. (For example, see GET-NTH-FROM-LAST-PLAY,
;; ADD-TO-HISTORY, etc.)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (play-loop strategy1 strategy2)
;; returns final scores
(define (play-loop-helper strat1 strat2 history1 history2 counter limit)
(if (= counter limit)
(final-scores history1 history2 limit)
(let ((result1 (strat1 history1 history2))
(result2 (strat2 history2 history1)))
;; note that the strategy's
;; own history comes first
(play-loop-helper strat1 strat2
(add-to-history result1 history1)
(add-to-history result2 history2)
(1+ counter)
limit)))) ; end of helper
(play-loop-helper strategy1 strategy2 ; play-loop body
empty-history empty-history
0
(+ 90 (random 21))))
(define (final-scores history1 history2 num-of-rounds)
;; returns average score per round for the two histories
(se (/ (get-scores history1 history2) num-of-rounds)
(/ (get-scores history2 history1) num-of-rounds) ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Procedures about histories
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define empty-history '())
(define empty-history? empty?)
(define (add-to-history result history)
(se history result))
(define (last-play history)
(last history))
(define (previous-history history)
(bl history))
(define (get-nth-to-last-play n history)
(cond ((empty? history) '())
((= n 1) (last history))
(else (get-nth-to-last-play (1- n) (butlast history)))))
(define (get-scores my-hist other-hist)
;; returns total score for first player
(if (or (empty? my-hist) (empty? other-hist))
0
(+ (get-score (first my-hist) (first other-hist))
(get-scores (bf my-hist) (bf other-hist)))))
(define (get-score my-play other-play)
;; returns the score of the first player for this round
(let ((round (se my-play other-play)))
(cond ((equal? round '(C C)) 3)
((equal? round '(C D)) 0)
((equal? round '(D C)) 5)
((equal? round '(D D)) 1) )))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Some strategies.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (all-defect my-history other-history)
'D)
(define (poor-trusting-fool my-history other-history)
'C)
(define (unforgiving my-history other-history)
(define (ever-defected? history)
(if (empty-history? history)
#f
(or (equal? (last-play history) 'D)
(ever-defected? (previous-history history)))))
(if (ever-defected? other-history) 'D 'C))
(define (tit-for-tat my-history other-history)
(if (empty-history? other-history)
'C
(last-play other-history)))
(define (random-strategy my-history other-history)
(nth (random 2) '(C D)))
|