1.3 Server
1.3.1 Sequence
1.3.2 Cargos
1.3.3 Grid
1.3.4 Engine
1.3.5 Setup
1.3.6 Agent
1.3.7 Interval
1.3.8 Dispatcher
1.3.9 TCP Server
8.14
1.3.6 Agent🔗

Source code at agent.rkt

An agent represents a body of code that interacts with the game. This may be a player client, or a game viewer client.

(struct agent ([type #:mutable]))
(define (make-agent) (agent 'unassigned))

The first request sent to the agent sets its type. A draw request means the agent is a game viewer. A hello request means the agent is a game player.

(test-case:
 "set type"
 (define (check-type request)
   (let ([agent (make-agent)])
     (set-type! agent request)
     (agent-type agent)))
 (check-equal? (check-type request-draw) 'viewer)
 (check-equal? (check-type request-hello) 'player))

If the agent type is unassigned, it means that the type hasn’t been set yet. Once set, the type doesn’t change.

(define (set-type! agent request)
  (when (equal? (agent-type agent) 'unassigned)
    (cond
      [(equal? request request-hello) (set-agent-type! agent 'player)]
      [(equal? request request-draw) (set-agent-type! agent 'viewer)])))

An agent checks if a request is valid, based on the agent type.

(test-case:
 "valid request"
 (let ([agent (agent 'unassigned)])
   (check-true (request-is-valid? agent request-draw))
   (check-true (request-is-valid? agent request-hello))
   (check-false (request-is-valid? agent '(#f))))
 (let ([agent (agent 'viewer)])
   (check-true (request-is-valid? agent request-draw))
   (check-false (request-is-valid? agent request-hello))
   (check-false (request-is-valid? agent '(#f))))
 (let ([agent (agent 'player)])
   (check-false (request-is-valid? agent request-draw))
   (check-false (request-is-valid? agent request-hello))
   (check-true (request-is-valid? agent '(#f)))))

If the type hasn’t been set yet, a draw or hello request is valid. For a game viewer, only draw requests are OK. For a game player, each request must be a list of commands.

(define (request-is-valid? agent request)
  (let ([type (agent-type agent)])
    (cond
      [(equal? type 'unassigned)
       (or (equal? request request-hello) (equal? request request-draw))]
      [(equal? type 'viewer) (equal? request request-draw)]
      [(equal? type 'player) (list? request)])))

An agent matches a request by checking if the request is valid, and setting the agent type.

(test-case:
 "match request"
 (let ([agent (make-agent)])
   (check-false (match-request agent '(#f)))
   (check-equal? (agent-type agent) 'unassigned)
   (check-true (match-request agent request-draw))
   (check-equal? (agent-type agent) 'viewer)))

If the request is not valid, the type is not changed. The result of the valid check is returned.

(define (match-request agent request)
  (let ([valid? (request-is-valid? agent request)])
    (when valid? (set-type! agent request))
    valid?))