1.3 The Code
1.3.2 Client
1.3.2.1 Connection
1.3.2.2 Bot
1.3.2.3 Step
1.3.2.4 Tactics
1.3.2.5 Wandering
1.3.2.6 TCP Client
1.3.2.7 Viewer
1.3.2.8 TCP Viewer
8.14
1.3.2.2 Bot🔗

Source code at bot.rkt

A bot is an entity that is controlled by client code. It can pick up a block entity. This is stored in the cargo field. It also has a list of nearby entities that it can see, in the neighbors field.

(struct bot (id location cargo neighbors))

(define (make-bot reply)
  (bot (reply-id reply) (reply-location reply) (reply-cargo reply)
       (reply-neighbors reply)))

Adjacent entities are ones at locations adjacent to the bot’s location.

(test-case:
 "adjacent block found"
 (let* ([bot1 (entity 101 type-bot)]
        [block1 (entity 102 type-block)]
        [block2 (entity 102 type-block)]
        [bot2 (entity 103 type-bot)]
        [bot (bot bot1 (location 1 1) #f
                  (list (occupant bot2 (location 2 1))
                        (occupant block1 (location 1 2))
                        (occupant block2 (location 2 2))))]
        [adjacent (adjacent-entities bot type-block)])
   (check-equal? (length adjacent) 1)
   (check-equal? (first adjacent) (occupant block1 (location 1 2)))))
(test-case:
 "block not adjacent"
 (let* ([bot1 (entity 101 type-bot)]
        [block1 (entity 102 type-block)]
        [block2 (entity 102 type-block)]
        [bot (bot bot1 (location 1 1) #f
                  (list (occupant block1 (location 0 2))
                        (occupant block2 (location 2 2))))]
        [adjacent (adjacent-entities bot type-block)])
   (check-equal? (length adjacent) 0)))

We filter the bot’s neighbors to find adjacent entities of a requested type.

(define (adjacent-entities bot type)
  (filter (λ (neighbor)
            (and (= (occupant-type neighbor) type)
                 (adjacent? (occupant-location neighbor) (bot-location bot))))
          (bot-neighbors bot)))

A bot can change direction.

(test-case:
 "new direction is different"
 (let* ([bot1 (entity 101 type-bot)]
        [block (entity 102 type-block)]
        [bot (bot bot1 (location 1 1) #f (list (occupant block (location 1 2))))]
        [new (change-direction bot direction-west)])
   (check-true (or (equal? new direction-east) (equal? new direction-south)))
   (check-false (and (equal? new direction-north) (equal? new direction-west)))))

A new direction is chosen at random from the valid candidates. If there are no candidates, the direction is unchanged.

(define (change-direction bot old-direction)
  (define (valid-change? location)
    (not (findf (λ (neighbor) (equal? location (occupant-location neighbor)))
                (bot-neighbors bot))))
  (let* ([candidates
          (filter valid-change? (all-directions (bot-location bot) #:except old-direction))]
         [count (length candidates)])
    (if (= count 0)
        old-direction
        (direction-from (bot-location bot) (list-ref candidates (random count))))))