game-of-life.scm 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. ;;; game-of-life --- Conway's Game of Life in Pre-Scheme
  2. (define WINDOW_TITLE "Conway's Game of Life")
  3. (define WINDOW_WIDTH 1280)
  4. (define WINDOW_HEIGHT 800)
  5. (define CELL_SIZE 5)
  6. (define FRAME_DELAY 50)
  7. (define GRID_WIDTH (quotient WINDOW_WIDTH CELL_SIZE))
  8. (define GRID_HEIGHT (quotient WINDOW_HEIGHT CELL_SIZE))
  9. (define (main argc argv)
  10. (ensure-args argc argv)
  11. (with-sdl
  12. (sdl-init SDL_INIT_VIDEO)
  13. (lambda ()
  14. (with-sdl-window
  15. (sdl-create-window WINDOW_TITLE
  16. SDL_WINDOWPOS_CENTERED
  17. SDL_WINDOWPOS_CENTERED
  18. WINDOW_WIDTH
  19. WINDOW_HEIGHT
  20. SDL_WINDOW_SHOWN)
  21. (lambda (window)
  22. (with-sdl-renderer
  23. (sdl-create-renderer window -1 SDL_RENDERER_ACCELERATED)
  24. (lambda (renderer)
  25. (with-sdl-event
  26. (lambda (event)
  27. (run-application window renderer event))))))))))
  28. (define (ensure-args argc argv)
  29. ;; type inference hack to get the right signature for main
  30. (string-length (vector-ref argv (- argc 1)))
  31. (unspecific))
  32. (define (handle-sdl-error message)
  33. (define out (current-error-port))
  34. (write-string message out)
  35. (write-string ": " out)
  36. (write-string (sdl-get-error) out)
  37. (newline out)
  38. -1)
  39. (define (with-sdl initialized? thunk)
  40. (if (not initialized?)
  41. (handle-sdl-error "Could not initialize SDL")
  42. (let ((result (thunk)))
  43. (sdl-quit)
  44. result)))
  45. (define (with-sdl-window window proc)
  46. (if (null-pointer? window)
  47. (handle-sdl-error "Could not create window")
  48. (let ((result (proc window)))
  49. (sdl-destroy-window window)
  50. result)))
  51. (define (with-sdl-renderer renderer proc)
  52. (if (null-pointer? renderer)
  53. (handle-sdl-error "Could not create renderer")
  54. (let ((result (proc renderer)))
  55. (sdl-destroy-renderer renderer)
  56. result)))
  57. (define (with-sdl-event proc)
  58. (let* ((event (sdl-create-event))
  59. (result (proc event)))
  60. (sdl-destroy-event event)
  61. result))
  62. (define (run-application window renderer event)
  63. (let ((grid (initialize-grid)))
  64. (let loop ((running? #t))
  65. (when running?
  66. (cond ((sdl-poll-event event)
  67. (if (= (sdl-event-type event) SDL_QUIT)
  68. (goto loop #f)
  69. (goto loop #t)))
  70. (else
  71. (update-grid grid)
  72. (render-grid grid renderer)
  73. (sdl-delay FRAME_DELAY)
  74. (goto loop #t)))))
  75. (destroy-grid grid)
  76. 0))
  77. (define (initialize-grid)
  78. (define c_srand (external "srand" (=> (integer) unit)))
  79. (define c_rand (external "rand" (=> () integer)))
  80. (define c_time (external "time" (=> (integer) integer)))
  81. (c_srand (c_time 0))
  82. (grid-unfold (lambda (ix x y)
  83. (remainder (c_rand) 2))
  84. GRID_WIDTH GRID_HEIGHT))
  85. (define (update-grid grid)
  86. (grid-update! (lambda (ix x y value)
  87. (let ((north (grid-ref grid x (- y 1)))
  88. (south (grid-ref grid x (+ y 1)))
  89. (east (grid-ref grid (+ x 1) y))
  90. (west (grid-ref grid (- x 1) y))
  91. (north-east (grid-ref grid (+ x 1) (- y 1)))
  92. (north-west (grid-ref grid (- x 1) (- y 1)))
  93. (south-east (grid-ref grid (+ x 1) (+ y 1)))
  94. (south-west (grid-ref grid (- x 1) (+ y 1))))
  95. (let ((alive? (one? value))
  96. (live-neighbours (+ north south east west
  97. north-east north-west
  98. south-east south-west)))
  99. (if alive?
  100. (cond ((< live-neighbours 2) 0) ;; underpopulation
  101. ((> live-neighbours 3) 0) ;; overpopulation
  102. (else 1))
  103. (cond ((= live-neighbours 3) 1) ;; reproduction
  104. (else 0))))))
  105. grid))
  106. (define (render-grid grid renderer)
  107. (sdl-set-render-draw-color renderer 0 0 0 255)
  108. (sdl-render-clear renderer)
  109. (sdl-set-render-draw-color renderer 255 255 255 255)
  110. (grid-for-each (lambda (ix x y value)
  111. (unless (zero? value)
  112. (sdl-render-fill-rect renderer
  113. (* x CELL_SIZE)
  114. (* y CELL_SIZE)
  115. CELL_SIZE
  116. CELL_SIZE)
  117. (unspecific)))
  118. grid)
  119. (sdl-render-present renderer)
  120. (unspecific))