Overview

The simple-model.rkt module defines a simple, deterministic, model for testing purposes. As discussed in the previous step, a model is defined by a function for generating the initial grid, a function for update the grid, and a predicate for testing if the grid has stabilized. We ignore the initial grid for the moment and focus on the other two components:

The Simple Model

The simple model uses the following rules:

  • A cell can be either Well, Ill, or Immune.

  • If a Well cell has two or more Ill neighbors, then the cell becomes Ill.

  • A cell remains Ill for five simulation steps, at which point the cell becomes Immune.

  • The simulation is stable when either every cell is Immune or there are no Well cells with two or more Ill neighbors.

Cells

The first step is to define a representation of cells in the grid: Add the following definitions to your code:

;; the health of a cell
(define-type Health (U 'Well 'Ill 'Immune))

;; A (Cell health ticks) represents the state of a grid cell, where health is the current
;; health of the cell and ticks is the number of simulation steps until an ill cell
;; turns immune.  If the cell is not ill, then ticks should be 0.
(define-struct Simple-Cell
  ([health : Health]
   [recovery-time : Integer]))

(: is-ill? : Simple-Cell -> Boolean)
(define (is-ill? cell) (symbol=? (Simple-Cell-health cell) 'Ill))

;; a grid of cells in the simple model
(define-type Simple-Grid (Grid Simple-Cell))

Updating the Grid

Update the grid for a simulation step basically requires updating every cell according to the above rules. Implement a function with the following signature

(: update-cell : Simple-Grid -> Coord Simple-Cell -> Simple-Cell)

that takes a grid argument and returns a function for updating individual cells. With this function in hand, it is easy to define a function for updating the whole grid:

(: update-grid : Simple-Grid -> Simple-Grid)
;; update the grid for one time step
(define (update-grid grid)
  (grid-map-with-coord (update-cell grid) grid))

Checking for a Stable Grid

You should implement the following function that tests if a grid is stable (as described above):

(: stable? : Simple-Grid -> Boolean)

Since both this function and the update-cell function require counting the number of Ill neighbors, you may be able to factor out common code into a helper function.

Building a Model

Since the main purpose of the simple model is to serve as a test case for the other parts of the project, we want to be able to specify specific initial grids. We do this by supplying a list of initial cell values that are used to update an initial grid where everyone is Well.

Add the following utility type definition to the simple-model.rkt file:

;; A specified initial cell value
(define-struct Simple-Init-Cell
  ([coord : Coord]
   [health : Health]
   [recovery-time : Integer]))

We provide the following function for generating an initial grid:

(: initial-grid : (Listof Simple-Init-Cell) -> Natural Natural -> Simple-Grid)
;; generate an initial grid from a list of initial cell values and
;; the grid dimensions.
(define (initial-grid init-cells)
  (lambda ([nr : Natural] [nc : Natural])
    (local
      {(: update : Simple-Init-Cell Simple-Grid -> Simple-Grid)
       ;; update a single cell as specified by the initial cell value
       (define (update init-cell grid)
         (match init-cell
           [(Simple-Init-Cell (Coord r c) h t)
            (grid-set grid (Coord (modulo r nr) (modulo c nc)) (Simple-Cell h t))]))}
      ;; apply the update operation for each initial cell value
      (foldl update
             (build-grid nr nc (lambda ([c : Coord]) (Simple-Cell 'Well 0)))
             init-cells))))

The you can define a function make-simple-model that takes a list of initial cell values and returns a Simple-Cell model.

(: make-simple-model : (Listof Simple-Init-Cell) -> (Model Simple-Cell))

Rendering

The simple-model.rkt file also defines support for rendering cells in the simple model. Draw the cells as circles with black outlines and where the fill color depends on the health of the cell. Implement a function for creating the rendering information for the simple model from the cell radius and the refresh rate:

(: render-simple-model : Integer Positive-Real -> (Render-Info Simple-Cell))

Exports

;; ===== Exports =====

(provide (struct-out Simple-Init-Cell)
         Simple-Cell
         Simple-Grid)

(provide make-simple-model
         render-simple-model)