msim-far.lisp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. ; msim by Farooq Karimi Zadeh <fkz@riseup.net>
  2. ; Copyright (c) 2019 Farooq Karimi Zadeh
  3. ; Under MIT/X11 Licence (see LICENSE)
  4. (defun random-choice (L) (nth (random (length L)) L))
  5. (defun vote (citizens)
  6. (let* ((votes (loop for i in citizens collect (list 0 i))))
  7. (loop for citizen in citizens do
  8. (case citizen
  9. ('f (loop for i = (random-choice votes)
  10. unless (equal (second i) 'f)
  11. do (progn
  12. (incf (first i))
  13. (return))))
  14. ('m (loop for i = (random-choice votes)
  15. unless (equal (second i) 'm)
  16. do (progn
  17. (incf (first i))
  18. (return))))
  19. ('r (incf (first (random-choice votes))))))
  20. (second (reduce (lambda (x y) (if (> (first x) (first y)) x y)) votes))))
  21. (defun night-kill (citizens)
  22. (remove (random-choice (remove 'm citizens)) citizens :count 1))
  23. (defun day-lynch (citizens)
  24. (let ((tmp (vote citizens)))
  25. (if (equal tmp 'f)
  26. 'fool-win
  27. (remove tmp citizens :count 1))))
  28. (defun mafiawin? (citizens)
  29. (when (<= (/ (length citizens) 2) (count 'm citizens))
  30. t))
  31. (defun towniewin? (citizens)
  32. (when (zerop (count 'm citizens))
  33. t))
  34. (defun play-game (citizens)
  35. (loop
  36. (setf citizens (night-kill citizens))
  37. (setf citizens (day-lynch citizens))
  38. (when (eql 'fool-win citizens)
  39. (return 'fool-win))
  40. (cond
  41. ((towniewin? citizens) (return 'townie-win))
  42. ((mafiawin? citizens) (return 'mafia-win)))))
  43. (defun sim (rounds citizens)
  44. (let ((fool-win 0)
  45. (mafia-win 0)
  46. (townie-win 0))
  47. (loop
  48. for result = (play-game citizens)
  49. repeat rounds
  50. do
  51. (case result
  52. ('fool-win (incf fool-win))
  53. ('townie-win (incf townie-win))
  54. ('mafia-win (incf mafia-win))))
  55. (list :f fool-win :m mafia-win :t townie-win)))
  56. (defun sim-mt (nthreads citizens nrounds)
  57. (let* ((threads (loop
  58. repeat nthreads
  59. collect (sb-thread:make-thread #'sim :arguments (list nrounds citizens))))
  60. (result (list :f 0 :m 0 :t 0)))
  61. (loop for thread in threads do
  62. (progn
  63. (incf (getf result :f) (getf (sb-thread:join-thread thread) :f))
  64. (incf (getf result :m) (getf (sb-thread:join-thread thread) :m))
  65. (incf (getf result :t) (getf (sb-thread:join-thread thread) :t))))
  66. result))