;Lowball monitor and default agents ;Designed by Robert Levinson ;Programmed by Foaad Khosmood ;Agent VallsVargas by Josep Valls ;for CMPS140-Winter 2008, UC Santa Cruz ;Dec. 13, 2007 by Foaad: Added support for real-valued bank balances ;-- also added 100 round drop. (lowest scoring agent drops every 100 rounds) (defun l () (load "lowball.lisp")) (defun s () (lowball agentlist 100)) (defvar verbose) (setf verbose 0) (defvar maxRoundCounter) (defvar roundCounter 0) (defvar finalRanking nil) (let (r betsh willbet numbers) (setf r 0 betsh () willbet 1 numbers ()) (defun VallsVargas (balance lastRound) balance lastRound (incf r) ;(format t "balance ~A ~%" balance) ;(print lastRound) (cond ;initializing, play low ((= r 1) 1) ((= r 2) (progn (setf betsh lastround) 2)) ;learning, play random ((> r 2) (progn (setf betsh (mapcar #'(lambda (agentStatus) (append (list (first agentStatus)) (rest (first (remove-if-not #'(lambda(agent2) (if (equal (first agent2) (first agentStatus)) 1 nil)) betsh))) (list (second agentstatus)))) lastRound) ) ;(print betsh) (setf numbers (loop for i from 1 to 100 collect i)) (setf numbers2 (mapcar #'(lambda (number) (append (list number) (list (apply #'+ (mapcar #'(lambda (number2) (if (= number2 number) 1 0)) (apply #'append (mapcar #'(lambda (agent) (rest agent)) betsh)) ))) )) numbers)) (setf numbers3 (stable-sort numbers2 #'(lambda (x y) (< (second x) (second y))))) (print numbers3) ;(print lastround) (setf willbet (+ 1 (random 6))) (setf willbet (first (first numbers3))) ;i have to fight the agents that play 1 and 2 (if (and (> balance 180) (= (mod r 5) 0)) (setf willbet (+ 1 (random 2)))) (if (and (> balance 180) (= (mod r 2) 0)) (setf willbet 1)) ;(print willbet) (if (< willbet balance) willbet 1) ) ) ;for safety (t 1)))) (defvar agentlist) (setf agentlist '(SingleMinded MaxRisky JamesBond AynRand TwoFace KingSolomon W Trotsky SamuraiJack Crazy88 VallsVargas)) ;(load "p2lb_agents.sparcf") ;(setf agentlist (append agentlist a)) (defun SingleMinded (balance lastRound) balance lastRound ;(format t "~% >>>>>>>> lastRound: ~A ~%" lastRound) 1) (defun MaxRisky (balance lastRound) lastRound (cond ((> balance 1) (floor balance)) (t 1))) (defun JamesBond (balance lastRound) lastRound (cond ((> balance 7) 7) ((> balance 1) (+ 1 (random (floor balance)))) (t 1))) (defun AynRand (balance lastRound) lastRound (+ 1 (random (floor balance)))) (defun TwoFace (balance lastRound) lastRound (if (= balance 1) 1 2)) (defun KingSolomon (balance lastRound) lastRound (if (< balance 3) 1 (floor balance 2))) (defun W (balance lastRound) lastRound (max 1 (random (floor (* balance 1.1))))) (defun Trotsky (balance lastRound) (max 1 (min (floor balance) (max 1 (round (* (sqrt (length lastRound)) 2)))))) (defun SamuraiJack (balance lastRound) lastRound (if (> (random 10) 7) 1 (if (> (random 10) 8) (min (floor balance) 111) (min (floor balance) 11)))) (defun Crazy88 (balance lastRound) lastRound (min (floor balance) (cond ((< balance 10) 1) ((> (length lastRound) 8) 8) ((> (length lastRound) 3) (+ 2 (random 8))) (t (max 1 (floor (random 8) 2)))))) ;takes in standings which is list of (agent holding) pairs + ; history of last round's wagers which is just a list of integers ;returns a list of wagers (agent balance wager) triples (defun getWagers (standings lastRound) (mapcar #'(lambda (agent) (list (car agent) (second agent) (floor (funcall (car agent) (second agent) lastRound)))) standings)) ;checks one single wager for legality (defun isLegal (agentWager) (let ((name (first agentWager)) (balance (second agentWager)) (wager (third agentWager))) (cond ((> wager balance) (progn (format t "~% ILLEGAL MOVE: ~A tried to wager ~A when it only has ~A balance. ~%" name wager balance) nil)) ((< wager 1) (progn (format t "~% ILLEGAL MOVE: ~A wagered ~A, which is lower than 1." name wager) nil)) ((> (/ wager (floor wager)) 1) (progn (format t "~% ILLEGAL MOVE: ~A wagered ~A which is not a whole number." name wager)) nil) (t t)))) ;check boundaries and legality, drop any agents that violate the rules (defun legalCheck (standingsWager) (cond ((null standingsWager) nil) ((isLegal (car standingsWager)) (cons (car standingsWager) (legalCheck (cdr standingsWager)))) (t (progn (format t "~% Agent ~A has been ejected for illegal activity. ~%" (caar standingsWager)) (setf finalRanking (cons (caar standingsWager) finalRanking)) (setf roundCounter 0) (legalCheck (cdr standingsWager)))))) (defun occurrences (l) ; from P1 question 3.3, except unsorted (if (null l) nil (cons (cons (car l) (count (car l) l) ) (occurrences (remove (car l) l))))) ;takes in list of (wager, number_of_occurrences) pairs ;returns (total_number_of_ties, total_sum_of_ties, list_of_ties) (defun tieCalc (l) (cond ((null l) (list 0 0 nil)) ((> (cdar l) 1) (list (+ (first (tieCalc (cdr l))) (cdar l)) (+ (second (tieCalc (cdr l))) (* (caar l) (cdar l))) (cons (caar l) (remove (caar l) (third (tieCalc (cdr l))))))) (t (tieCalc (cdr l))))) ;wagers are really list of "(name balance bets)" triples ;returns adjusted standings as list of "(name balance)" pairs (defun evaluateRound (wagers) (let* ( (numAgents (length wagers)) (maxWinners (floor numAgents 2)) (minLosers (- numAgents maxWinners)) (plays (mapcar #'(lambda (wager) (third wager)) wagers)) (multiCounts (occurrences plays)) (tieCalcResults (tieCalc multiCounts)) (numTies (first tieCalcResults)) (listTies (sort (third tieCalcResults) #'<)) (listNonTies (sort (set-difference plays listTies) #'< )) (losingBids (if (>= numTies minLosers) listTies (union listTies (member (nth maxWinners listNonTies) listNonTies)))) (winningBids (set-difference plays losingBids)) (pot (+ (second tieCalcResults) (reduce #'+ (set-difference listNonTies winningBids))))) (when (> verbose 3) (format t "~%>>>numAgents=~A, maxWinners=~A, minLosers=~A, multiCounts=~A, listTies=~A, listNT=~A" numAgents maxWinners minLosers multiCounts listTies listNonTies)) (when (> verbose 2) (format t "~% >>> Balance/Bets: ~A" wagers)) (when (> verbose 3) (format t "~% >>> plays = ~A, wins = ~A, loss = ~A , pot = ~A~%" plays winningBids losingBids pot)) (adjustStandings wagers winningBids pot))) (defun rnd2 (a) (/ (truncate (* a 100.0)) 100.0)) (defun adjustStandings (standingsWagers winningBids pot) (let ((sumWinners (reduce #'+ winningBids))) (mapcar #'(lambda (agentStatus) (let ((name (first agentStatus)) (balance (second agentStatus)) (bid (third agentStatus))) (if (member bid winningBids) (progn (when (> verbose 3) (format t "~% ~A WINS: +~A" name (rnd2 (/ (* bid pot 1.0) sumWinners)))) (list name (+ balance (rnd2 (/ (* bid pot 1.0) sumWinners))))) (progn (when (> verbose 3) (format t "~% ~A LOSES: -~A" name bid)) (list name (- balance bid)))))) standingsWagers))) ;remove bankrupted agents (defun removeBankrupts (standings) (cond ((null standings) nil) ((>= (second (car standings)) 1) (cons (car standings) (removeBankrupts (cdr standings)))) (t (progn (format t "~% Agent ~A is bankrupt! ~%" (caar standings)) (setf finalRanking (cons (caar standings) finalRanking)) (removeBankrupts (cdr standings)))))) (defun getLowstScore(standings) (car (sort (mapcar #'(lambda (agentStatus) (second agentStatus)) standings) #'<))) (defun removeScore(standings score) (cond ((null standings) nil) ((/= (second (car standings)) score) (cons (car standings) (removeScore (cdr standings) score))) (t (progn (format t "~% Agent ~A is Removed for having the lowest balance. ~%" (caar standings)) (setf finalRanking (cons (caar standings) finalRanking)) (removeScore (cdr standings) score))))) ;removeOneAgent (defun removeOneAgent (standings) (let ((notBankrupted (removeBankrupts standings))) (if (and (= (length notBankrupted) (length standings)) (>= roundCounter maxRoundCounter)) (progn (setf roundCounter 0) (removeScore standings (getLowstScore standings))) (progn (setf roundCounter (+ 1 roundCounter)) notBankrupted)))) ;Print Status (defun printStatus (standings) (format t "~% =================================================== ~%") (format t "~% Current Standings: ~A ~%" (sort standings #'(lambda (x y) (> (second x) (second y))))) (format t "~% =================================================== ~%")) ;main monitor (defun lowBallMonitor(standings lastRound) (if (= (length standings) 1) (caar standings) (let* ((statusBids (legalCheck (getWagers standings lastRound))) (bids (mapcar #'(lambda (agentStatus) (list (first agentStatus)(third agentStatus))) statusBids))) ;step through rounds press enter ;(read-char *standard-input*) (when (> verbose 0) (printStatus standings)) (when (> verbose 1) (format t "~% >>> Wagers: ~A ~%" bids)) (lowBallMonitor (removeOneAgent (evaluateRound statusBids)) bids)))) ;print Final Rankings (defun printFinalRanking (l) (if (null l) nil (cons (list (length l) (car (last l))) (printFinalRanking (butlast l))))) ;initiater (defun lowball (agents initialBank) (let* ((standings (mapcar #'(lambda (agent) (list agent initialBank)) agents))) (progn ;sets how often agents are ejected due to being lowest (setf maxRoundCounter 100) ;holds final rankings (setf finalRanking nil) (format t "~% Final Ranking: ~A ~%" (reverse (printFinalRanking (cons (lowBallMonitor standings nil) finalRanking)))))))