Remote agent/Simulation

From Rosetta Code
Remote agent/Simulation is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
As described in Remote agent, generate a map, accept and respond to commands from an agent using an unbuffered stream.

C

See Remote agent/Simulation/C

PicoLisp

This is the server. For the client, see Remote agent/Agent logic#PicoLisp. After starting (gameServer), you might for testing purposes also connect with 'telnet', type the commands, and see the responses. <lang PicoLisp># Global variables:

  1. '*Port' is the port where the server is listening
  2. '*Sock' is the TCP socket after a client connected
  3. '*World' holds the current world
  4. '*Agent' is the field where the agent is in
  5. '*Ball' is the ball the agent is holding
  6. '*Dir' is a circular list of directions (north east south west .)

(load "@lib/simul.l")

  1. The server port

(setq *Port (port 54545))

  1. Return a random Field

(de randomField ()

  (get *World (rand 1 DX) (rand 1 DY)) )
  1. Create a world of size 'DX' * 'DY' with 'Balls' and 'Walls'

(de makeWorld (DX DY Balls Walls)

  (when (>= Balls (* DX DY))
     (quit "Too many balls") )
  (when (>= Walls (* (dec DX) (dec DY)))
     (quit "Too many walls") )
  (for Column (setq *World (grid DX DY))          # Initialize fields
     (for This Column
        (let Color (get '(R G Y B) (rand 1 4))
           (=: field Color)                       # Set field color
           (when (ge0 (dec 'Balls))
              (until
                 (with (randomField DX DY)        # Find a field without ball
                    (unless (: ball)              # and set a ball
                       (=: ball Color) ) ) ) ) ) ) )
  (do Walls                              # Create walls
     (until
        (let
           (Field (randomField DX DY)    # Try random field
              F (if (rand T) car cdr)    # and random side
              G (if (rand T) '(car set . con) '(cdr con . set))
              Old ((car G) (F (val Field))) )
           (when Old
              ((cadr G) (F (val Field)) NIL)  # Remove connections to neighbor
              ((cddr G) (F (val Old)) NIL)
              (or
                 (reachable? Field (* DX DY))  # Field still reachable?
                 (nil                          # No: Restore connections
                    ((cadr G) (F (val Field)) Old)
                    ((cddr G) (F (val Old)) Field) ) ) ) ) ) ) )
  1. Test whether a field is reachable

(de reachable? (Field Fields)

  (let Visited NIL
     (recur (Field)
        (when (and Field (not (memq Field Visited)))
           (push 'Visited Field)
           (recurse (west Field))
           (recurse (east Field))
           (recurse (south Field))
           (recurse (north Field)) ) )
     (= Fields (length Visited)) ) )
  1. Test for ending condition

(de ending? ()

  (nor
     *Ball
     (find
        '((Column)
           (find
              '((This)
                 (and (: ball) (n== (: field) (: ball))) )
              Column ) )
        *World ) ) )
  1. Initialize for a new game

(de newGame (DX DY Balls Walls)

  (makeWorld DX DY Balls Walls)
  (setq
     *Agent (randomField DX DY)
     *Dir (do (rand 1 4) (rot '(north east south west .))) ) )
  1. Start the game server

(de gameServer (DX DY Balls Walls)

  (loop
     (setq *Sock (listen *Port))
     (NIL (fork) (close *Port))
     (close *Sock) )
  (seed *Pid)  # Ensure private random sequence
  (in *Sock
     (out *Sock (prin "A"))  # Greeting
     (when (= "A" (char (rd 1)))
        (newGame DX DY Balls Walls)
        (and *Dbg (showWorld))
        (while (rd 1)
           (out *Sock
              (case (char @)  # Command character
                 ("\^"  # Forward
                    (ifn ((car *Dir) *Agent)  # Hit wall?
                       (prin "|")             # Yes: Bump event
                       (with (setq *Agent @)  # Else go to new position
                          (prin (: field))
                          (and (: ball) (prin (lowc @))) ) ) )
                 (">"  # Turn right
                    (pop '*Dir) )
                 ("<"  # Turn left
                    (do 3 (pop '*Dir)) )
                 ("@"  # Get ball
                    (with *Agent
                       (cond
                          ((not (: ball)) (prin "s"))  # No ball in sector
                          (*Ball (prin "A"))           # Agent full
                          (T
                             (setq *Ball (: ball))
                             (=: ball) ) ) ) )
                 ("!"  # Drop ball
                    (with *Agent
                       (cond
                          ((not *Ball) (prin "a"))  # No ball in agent
                          ((: ball) (prin "S"))     # Sector full
                          (T (=: ball *Ball)
                             (off *Ball)
                             (and (ending?) (prin "+")) ) ) ) ) )  # Game over
              (prin ".") ) ) ) )  # Stop event
  (bye) )
  1. Visualize (debug)

(de showWorld ()

  (disp *World 0
     '((This)
        (pack
           (if (== *Agent This) "*" " ")
           (: field)
           (if (: ball) (lowc @) " ") ) ) ) )</lang>

An online demo version of this server runs on port 54545 of "picolisp.com". It can be used for testing.

For local tests, you can start also it interactively:

: (newGame 8 8 20 40) (showWorld)
   +---+---+---+---+---+---+---+---+
 8 | R   Y | B | R   R   Br| Rb  Br|
   +   +   +   +   +   +---+---+   +
 7 | Yy  G   G   Gb| Y   Gg  Rr| Y |
   +---+   +   +   +---+   +---+   +
 6 | R   Y   B   Rr *G   Y | Y   Br|
   +---+---+   +   +---+---+   +---+
 5 | B   Ry  G   R | Yy  Yy  Y | B |
   +   +---+---+   +---+   +---+   +
 4 | R | R   R   Gg  B   G   B   Y |
   +   +---+---+   +---+---+   +   +
 3 | R   Rr| Y   B   G | Yr  B | R |
   +   +   +---+---+---+   +   +---+
 2 | Y | B | B   Bb  Gr  B   B   Yy|
   +   +   +   +   +---+   +---+   +
 1 | Rr| R   G   Gr  R   G   R | G |
   +---+---+---+---+---+---+---+---+
     a   b   c   d   e   f   g   h

This displays the field colors in upper case letters, the balls in lower case letters, and the position of the agent with an asterisk.


Run BASIC

<lang runbasic>dim stats(10) [loop] cls html "Please click a number or " button #ex,"Exit",[exit] print for i = 1 to 10

 val.i$ = "#val";i
 link #val.i$ ,str$(i),[click]
 html " Clicked:";stats(i);" times
"

next i wait

[click] num = val(mid$(EventKey$,5)) stats(num) = stats(num) + 1 goto [loop]

[exit] Print "Thanks for playing... BYE!"</lang>