Remote agent/Agent interface

From Rosetta Code
Revision as of 18:10, 3 January 2011 by rosettacode>Abu (Added PicoLisp)
Remote agent/Agent interface 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.

In Remote agent, a component is described that marshals commands and events between a stream and a program that issues commands and processes the resulting events. Using the protocol definition described there, build this component in a fashion idiomatic and natural to your language.

PicoLisp

The interface logic for the PicoLisp solution is directly integrated into the client Remote agent/Agent logic#PicoLisp.

Tcl

Works with: Tcl version 8.6

<lang tcl>package require Tcl 8.6

oo::class create AgentAPI {

   variable sock events sectorColor ballColor
   constructor {host port} {

set sock [socket $host $port] fconfigure $sock -buffering none -translation binary -encoding ascii \ -blocking 0 # Temporary hack; due to change interp alias {} yieldto {} ::tcl::unsupported::yieldTo coroutine ReaderCoroutine my ReadLoop

   }
   destructor {

if {[llength [info command ReaderCoroutine]]} { rename ReaderCoroutine {} } if {[llength [info command AgentCoroutine]]} { rename AgentCoroutine {} } if {$sock ne ""} { catch {close $sock} }

   }
   method Log message {
   }
   # Commands
   method ForwardStep {} {

my Log "action: forward" puts -nonewline $sock "^" my ProcessEvents [yield]

   }
   method TurnRight {} {

my Log "action: turn right" puts -nonewline $sock ">" my ProcessEvents [yield]

   }
   method TurnLeft {} {

my Log "action: turn left" puts -nonewline $sock "<" my ProcessEvents [yield]

   }
   method GetBall {} {

my Log "action: get ball" puts -nonewline $sock "@" my ProcessEvents [yield]

   }
   method DropBall {} {

my Log "action: drop ball" puts -nonewline $sock "!" my ProcessEvents [yield]

   }
   method ProcessEvents {events} {

set sectorColor {} set ballColor {} set err {} set done 0 foreach e $events { my Log "event: $e" switch [lindex $e 0] { sector {set sectorColor [lindex $e 1]} ball {set ballColor [lindex $e 1]} error {set err [lindex $e 1]} gameOver {set done 1} } } if {$err ne ""} {throw $err "can't do that: $err"} return $done

   }
   # Event demux
   method ReadLoop {} {

# Init handshake fileevent $sock readable [info coroutine] while 1 { yield if {[read $sock 1] eq "A"} break } puts -nonewline $sock "A" # Main loop; agent logic is in coroutine try { coroutine AgentCoroutine my Behavior while 1 { yield set ch [read $sock 1] switch $ch { "." { # Stop - end of events from move set e $events set events {} yieldto AgentCoroutine $e if {"gameOver" in $e} break } "+" {lappend events gameOver} "R" {lappend events {sector red}} "G" {lappend events {sector green}} "Y" {lappend events {sector yellow}} "B" {lappend events {sector blue}} "r" {lappend events {ball red}} "g" {lappend events {ball green}} "y" {lappend events {ball yellow}} "b" {lappend events {ball blue}} "|" {lappend events {error bumpedWall}} "S" {lappend events {error sectorFull}} "A" {lappend events {error agentFull}} "s" {lappend events {error sectorEmpty}} "a" {lappend events {error agentEmpty}} } } } finally { close $sock set sock "" }

   }
   method Behavior {} {

error "method not implemented"

   }

}</lang> Sample agent (not a good player of the game; just to show how to program to the interface): <lang tcl>oo::class create Agent {

   superclass AgentAPI
   variable sectorColor ballColor
   forward Behavior my MoveBehavior
   # How to move around
   method MoveBehavior {} {

set ball "" while 1 { try { while {rand() < 0.5} { my ForwardStep my BallBehavior } } trap bumpedWall {} {} if {rand() < 0.5} { my TurnLeft } else { my TurnRight } } set ::wonGame ok

   }
   # How to handle the ball once we've arrived in a square
   method BallBehavior {} {

upvar 1 ball ball anywhere anywhere if { $ball eq "" && $ballColor ne "" && $ballColor ne $sectorColor } then { set ball [set ballTarget $ballColor] set anywhere 0 my GetBall } elseif { $ball ne "" && ($ball eq $sectorColor || $anywhere) } { try { if {[my DropBall]} { return -code break } set ball "" } trap sectorFull {} { # Target square full; drop this ball anywhere set anywhere 1 } }

   }

}

Agent new "localhost" 12345 vwait wonGame</lang>