1.3 The Code
1.3.3 Server
1.3.3.1 Sequence
1.3.3.2 Board
1.3.3.3 Places
1.3.3.4 Engine
1.3.3.5 Background
1.3.3.6 Draw
1.3.3.7 Setup
1.3.3.8 Agent
1.3.3.9 Interval
1.3.3.10 Dispatcher
1.3.3.11 TCP Server
8.14
1.3.3.3 Places🔗

Source code at places.rkt

Places are a record of where all the entities in the game are located. This information is stored in a hash table. The key is an entity id, and the value is a placement structure containing the entity and its place.

(struct places (hash))
(define (make-places) (places (make-hash)))

(struct placement (entity place) #:transparent)

A place can be at a location on the game board. Otherwise, the place is the id of another entity that is carying the entity as cargo.

(test-case:
 "place types"
 (check-true (at-location? (location 1 2)))
 (check-false (at-location? 101)))

(define (at-location? place) (not (number? place)))

Two places are the same place if they have the same type and same value.

(test-case:
 "same place"
 (check-true (same-place? (location 1 1) (location 1 1)))
 (check-false (same-place? (location 1 1) (location 1 2)))
 (check-false (same-place? 101 (location 1 1)))
 (check-true (same-place? 101 101)))
(define (same-place? a b)
  (and (equal? (at-location? a) (at-location? b))
       (equal? a b)))

We can place an entity in the table and retrieve an occupant by id.

(test-case:
 "place and retrieve"
 (let ([places (make-places)]
       [block (entity 101 type-block)])
   (place-entity places block (location 1 2))
   (check-equal? (occupant-by-id places 101) (occupant block (location 1 2)))
   (place-entity places block 123)
   (check-false (occupant-by-id places 101))
   (check-false (occupant-by-id places 999))))

This is done with basic hash table functions.

(define (occupant-by-id places id)
  (let ([placement (hash-ref (places-hash places) id #f)])
    (and placement (at-location? (placement-place placement))
        (occupant (placement-entity placement) (placement-place placement)))))
(define (place-entity places entity place)
  (hash-set! (places-hash places) (entity-id entity) (placement entity place)))
(define (place-by-id places id)
  (let ([placement (hash-ref (places-hash places) id #f)])
    (and placement (placement-place placement))))

We can apply a procedure to all values in the table to filter and map occupants of locations. This can also be done to filter and map cargos.

(test-case:
 "map entities"
 (define (get-id entity place) (entity-id entity))
 (let ([places (make-places)])
   (place-entity places (entity 101 type-bot) (location 1 1))
   (place-entity places (entity 102 type-block) 101)
   (check-equal? (filter-map-occupants places get-id) '(101))
   (check-equal? (filter-map-cargos places get-id) '(102))))

The values in the table are checked for the type of place and then the procedure is applied.

(define (filter-map-occupants places procedure)
  (~>> places places-hash hash-values
       (filter-map (λ (item)
                     (and (at-location? (placement-place item))
                          (procedure (placement-entity item) (placement-place item)))))))
(define (filter-map-cargos places procedure)
  (~>> places places-hash hash-values
       (filter-map (λ (item)
                     (and (not (at-location? (placement-place item)))
                          (procedure (placement-entity item) (placement-place item)))))))

We can find an entity at a place.

(test-case:
 "retrieve by place"
 (let ([places (make-places)]
       [block1 (entity 101 type-block)]
       [block2 (entity 102 type-block)])
   (place-entity places block1 (location 1 2))
   (place-entity places block2 104)
   (place-entity places (entity 103 type-block) (location 2 4))
   (check-false (entity-at places 101))
   (check-equal? (entity-at places (location 1 2)) block1)
   (check-equal? (entity-at places 104) block2)))

The hash-values function returns a list of the values in the table. We can then find a instance matching a place.

(define (entity-at places place)
  (let ([match
            (~>> places places-hash hash-values
                 (findf (λ (placement) (same-place? place (placement-place placement)))))])
    (and match (placement-entity match))))