From: Kenny Tilton
Subject: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F3E30E6.9060107@nyc.rr.com>
Trying to do a little premature optimization over here.

The data I get back from a socket is a vector of numbers. They come from 
the RoboCup soccer server, which was originally a Lisp project, so those 
numbers are character codes of, god bless 'em, a sexpr:

   "(init l 2 before_kick_off)"

So I'd like to hand it to read, but (preemy opt) without making it into 
a new string.

I see read-from-string, but not read-from-vector. read-from-string won't 
eat vectors (damn strong-typing!). I also looked for a way to make a 
stream out of a vector, but did not find one.

My workaround is to have a big one-time allocated string and:

     (map-into *buffer$* #'code-char (subseq data 0 size))

and then also tell read-from-string about the size.

Did I miss the easy way to do this, or is this what Gray streams are for?

-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker

From: Christopher C. Stacy
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <ufzk15vmk.fsf@dtpq.com>
>>>>> On Sat, 16 Aug 2003 13:22:43 GMT, Kenny Tilton ("Kenny") writes:

 Kenny> Trying to do a little premature optimization over here.
 Kenny> The data I get back from a socket is a vector of numbers. They come
 Kenny> from the RoboCup soccer server, which was originally a Lisp project,
 Kenny> so those numbers are character codes of, god bless 'em, a sexpr:

 Kenny>    "(init l 2 before_kick_off)"

 Kenny> So I'd like to hand it to read, but (preemy opt) without
 Kenny> making it into a new string.

Can't you just call READ on the network stream in the first place?
From: Kenny Tilton
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F3E8F64.4030902@nyc.rr.com>
Christopher C. Stacy wrote:
>>>>>>On Sat, 16 Aug 2003 13:22:43 GMT, Kenny Tilton ("Kenny") writes:
>>>>>
> 
>  Kenny> Trying to do a little premature optimization over here.
>  Kenny> The data I get back from a socket is a vector of numbers. They come
>  Kenny> from the RoboCup soccer server, which was originally a Lisp project,
>  Kenny> so those numbers are character codes of, god bless 'em, a sexpr:
> 
>  Kenny>    "(init l 2 before_kick_off)"
> 
>  Kenny> So I'd like to hand it to read, but (preemy opt) without
>  Kenny> making it into a new string.
> 
> Can't you just call READ on the network stream in the first place?

Interesting. With db-sockets we can access the socket stream, but I do 
not see anything similar with acl sockets. I /do/ call 
mp:wait-for-input-available on the acl socket as if it were a stream, 
but that must be provided as a specialization; read complains the 
datagram socket is not a stream.

another problem is that the soccer server doc warns that messages can 
get truncated, so one may not always get the closing parens. what I do 
is stick a few extra on the end before doing the read-from-string.

-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker
From: James A. Crippen
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <m3zni8q2oh.fsf@kappa.unlambda.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> another problem is that the soccer server doc warns that messages can
> get truncated, so one may not always get the closing parens. what I do
> is stick a few extra on the end before doing the read-from-string.

That's pretty icky.  I'm not certain (no HyperSpec handy) but I don't
think that READ is guaranteed to DTRT with extra random closing
parens.  Ie, in some implementation it might signal an error rather
than just ignore them.  You'd then need to catch that error to make it
go away.  Maybe catch a number of errors, one for each, or bail out
when catching the first one.

And what do you do if you magically receive an extra paren from the
other end?

Just something to think about.

Here's a thought off the top of my head -- put some sort of flag
character at the end of your incoming stream that marks where it
ended.  Use something nearly impossible to receive except if the data
is mangled, like #xff or whatever.  Maybe use a couple so you have a
complex unique bit pattern.  Make a READ macro to handle that which
checks to see if there's still open parens and inserts the appropriate
number.

But that's getting pretty complicated.  Still, the idea of throwing a
handful of close parens on the end of the string in hopes of it
fixing any missing parens just doesn't seem very safe.

'james

-- 
James A. Crippen <james at unlambda.com> Lambda Unlimited
61.2204N, -149.8964W                     Recursion 'R' Us
Anchorage, Alaska, USA, Earth            Y = \f.(\x.f(xx))(\x.f(xx))
From: Kenny Tilton
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F3F755A.3050906@nyc.rr.com>
James A. Crippen wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>another problem is that the soccer server doc warns that messages can
>>get truncated, so one may not always get the closing parens. what I do
>>is stick a few extra on the end before doing the read-from-string.
> 
> 
> That's pretty icky.  I'm not certain (no HyperSpec handy) but I don't
> think that READ is guaranteed to DTRT with extra random closing
> parens.  Ie, in some implementation it might signal an error rather
> than just ignore them. 

Well, if worse comes to worst I can just look at the strings and balance 
them intelligently, since the syntax of the soccer server messages is so 
simple.

You just gave me an idea. I can name my team "Team'(((Kenny" in the hope 
of crashing an opponent who has to parse messages char-by-char on the 
chance their parser is buggy. They'll keep reading looking for the 
closing parens!

:)



-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker
From: Thomas F. Burdick
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <xcv65kveal8.fsf@conquest.OCF.Berkeley.EDU>
Kenny Tilton <·······@nyc.rr.com> writes:

> Trying to do a little premature optimization over here.
> 
> The data I get back from a socket is a vector of numbers. They come from 
> the RoboCup soccer server, which was originally a Lisp project, so those 
> numbers are character codes of, god bless 'em, a sexpr:
> 
>    "(init l 2 before_kick_off)"
> 
> So I'd like to hand it to read, but (preemy opt) without making it into 
> a new string.
> 
> I see read-from-string, but not read-from-vector. read-from-string won't 
> eat vectors (damn strong-typing!). I also looked for a way to make a 
> stream out of a vector, but did not find one.
> 
> My workaround is to have a big one-time allocated string and:
> 
>      (map-into *buffer$* #'code-char (subseq data 0 size))
> 
> and then also tell read-from-string about the size.
> 
> Did I miss the easy way to do this, or is this what Gray streams are for?

Well, I've used Gray streams to do something similar, but I'm pretty
sure it was less efficient than the alternative vector-bashing
approach (waaaaaaay more elegant, though, with the use of mixins).

If I were you, I'd do something like:

  (when (< (length *chars*) size)
    (setf (*chars* (make-array size :element-type 'character))))
  (setf (fill-pointer *chars*) size)
  (dotimes (i size) (setf (char *chars* i) (aref *codes* i)))
  (read-from-string *chars*)

Of course, you are leading up to a call to READ...

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Kenny Tilton
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F423CD6.6060800@nyc.rr.com>
Thomas F. Burdick wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>Trying to do a little premature optimization over here.
>>
>>The data I get back from a socket is a vector of numbers. They come from 
>>the RoboCup soccer server, which was originally a Lisp project, so those 
>>numbers are character codes of, god bless 'em, a sexpr:
>>
>>   "(init l 2 before_kick_off)"
>>
>>So I'd like to hand it to read, but (preemy opt) without making it into 
>>a new string.
>>
>>I see read-from-string, but not read-from-vector. read-from-string won't 
>>eat vectors (damn strong-typing!). I also looked for a way to make a 
>>stream out of a vector, but did not find one.
>>
>>My workaround is to have a big one-time allocated string and:
>>
>>     (map-into *buffer$* #'code-char (subseq data 0 size))
>>
>>and then also tell read-from-string about the size.
>>
>>Did I miss the easy way to do this, or is this what Gray streams are for?
> 
> 
> Well, I've used Gray streams to do something similar, but I'm pretty
> sure it was less efficient than the alternative vector-bashing
> approach (waaaaaaay more elegant, though, with the use of mixins).
> 
> If I were you, I'd do something like:
> 
>   (when (< (length *chars*) size)
>     (setf (*chars* (make-array size :element-type 'character))))
>   (setf (fill-pointer *chars*) size)
>   (dotimes (i size) (setf (char *chars* i) (aref *codes* i)))
>   (read-from-string *chars*)

OK, that's what I had, to hell with elegance, it stays. Only I did not 
have the fill-pointer bit. So that's what that does. And to think I was 
returning two values, the buffer and the size. Doh!



-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker
From: Thomas F. Burdick
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <xcv65kt32tc.fsf@famine.OCF.Berkeley.EDU>
Kenny Tilton <·······@nyc.rr.com> writes:

> Thomas F. Burdick wrote:
>
> > If I were you, I'd do something like:
> > 
> >   (when (< (length *chars*) size)
> >     (setf (*chars* (make-array size :element-type 'character))))
> >   (setf (fill-pointer *chars*) size)
> >   (dotimes (i size) (setf (char *chars* i) (aref *codes* i)))
> >   (read-from-string *chars*)

[ wow, that code's broken in just about every detail, but it got my point across ]

> OK, that's what I had, to hell with elegance, it stays. Only I did not 
> have the fill-pointer bit. So that's what that does. And to think I was 
> returning two values, the buffer and the size. Doh!

Oh, fill-pointers are beautiful!  When I make functions that read
objects from binary streams, I usually make an accompanying one that
reads from (vector (unsigned-byte 8))'s, making heavy use of one of my
favorite utility functions that Really Should Be In CL (<-- ironic capitals):

  (defun vector-shift (vector &optional (amount 1))
    (let* ((length (length vector))
           (new-length (- length amount)))
      (setf (subseq vector 0 new-length) (subseq vector amount length)
            (fill-pointer vector) new-length)
      vector))

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Kenny Tilton
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F427903.4050200@nyc.rr.com>
Thomas F. Burdick wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>Thomas F. Burdick wrote:
>>
>>
>>>If I were you, I'd do something like:
>>>
>>>  (when (< (length *chars*) size)
>>>    (setf (*chars* (make-array size :element-type 'character))))
>>>  (setf (fill-pointer *chars*) size)
>>>  (dotimes (i size) (setf (char *chars* i) (aref *codes* i)))
>>>  (read-from-string *chars*)
>>
> 
> [ wow, that code's broken in just about every detail, but it got my point across ]

<g> Good thing the warranty had run out by the time I pasted it in.

Anyway, I gotta come clean. Turns out I did throw efficiency to the wind 
(Joe woulda been proud) in my very first efforts, so anxious was I to 
see guys scurrying around the field; I let the ACL socket read function 
allocate space instead of providing it a buffer. And it reasonably 
enough returned a vector of numbers, not characters. Now I just pass it 
one of your dandy character arrays and read-from-string that.

Life is good. multiple-value-binds and subseqs and end args are dropping 
like flies over here.

gee, a significant cleanup, some new CL knowledge, and at least a little 
more efficiency. glad I spent time on this. :)

-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker
From: Joe Marshall
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <n0e6yfrg.fsf@ccs.neu.edu>
Kenny Tilton <·······@nyc.rr.com> writes:

> Trying to do a little premature optimization over here.

> My workaround is to have a big one-time allocated string and:
>
>      (map-into *buffer$* #'code-char (subseq data 0 size))
>
> and then also tell read-from-string about the size.

What's wrong with (map 'string #'code-char vector)?
Are you getting huge packets so fast and furious that you need to
worry about them?
From: Kenny Tilton
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F423C3B.1030302@nyc.rr.com>
Joe Marshall wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>Trying to do a little premature optimization over here.
> 
> 
>>My workaround is to have a big one-time allocated string and:
>>
>>     (map-into *buffer$* #'code-char (subseq data 0 size))
>>
>>and then also tell read-from-string about the size.
> 
> 
> What's wrong with (map 'string #'code-char vector)?
> Are you getting huge packets so fast and furious that you need to
> worry about them?

What part of "premature optimization" do you not understand?! <g>

No, seriously, I do not think the injunction against preemy-opt excuses 
needless consing which could be avoided if I used the right magic CL 
incantation (or if I stick with plan A, which was to copy the data char 
by char into a string).

fwiw, the traffic is two or three messages every 100ms, each message 
hundreds (but not thousands) of characters long. Multiplied by 22, since 
I hope to run entire games from one Lisp image during development.



-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker
From: Joe Marshall
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3cfxegw7.fsf@ccs.neu.edu>
Kenny Tilton <·······@nyc.rr.com> writes:

> Joe Marshall wrote:
>> Kenny Tilton <·······@nyc.rr.com> writes:
>>
>>>Trying to do a little premature optimization over here.
>>
>>>My workaround is to have a big one-time allocated string and:
>>>
>>>     (map-into *buffer$* #'code-char (subseq data 0 size))
>>>
>>>and then also tell read-from-string about the size.
>> What's wrong with (map 'string #'code-char vector)?
>> Are you getting huge packets so fast and furious that you need to
>> worry about them?
>
> What part of "premature optimization" do you not understand?! <g>

Yeah, yeah.

> No, seriously, I do not think the injunction against preemy-opt
> excuses needless consing which could be avoided if I used the right
> magic CL incantation (or if I stick with plan A, which was to copy the
> data char by char into a string).

I'm guessing that the amount of CPU time you will save by avoiding
this `needless' consing will *never* add up to the amount of time
you've thought about it.

> fwiw, the traffic is two or three messages every 100ms, each message
> hundreds (but not thousands) of characters long. Multiplied by 22,
> since I hope to run entire games from one Lisp image during
> development.

Not enough to worry about.  Just cons it.
From: Scott A Douglass
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <9087817.1061401688@Moby.psy.cmu.edu>
> The data I get back from a socket is a vector of numbers. They come from
> the RoboCup soccer server, which was originally a Lisp project, so those
> numbers are character codes of, god bless 'em, a sexpr:
>
>    "(init l 2 before_kick_off)"
>
> So I'd like to hand it to read, but (preemy opt) without making it into a
> new string.
>
> I see read-from-string, but not read-from-vector. read-from-string won't
> eat vectors (damn strong-typing!). I also looked for a way to make a
> stream out of a vector, but did not find one.

Hmmm... we interface our agents to RoboCup with code like...


(defparameter *port-for-RS-server* 6000)
(defparameter *RS-client-plist* NIL)
(defparameter *default-RS-socket* NIL)


(defparameter *RS-buffer*
  (make-array 3000 :element-type 'character))


(defun make-UDP-socket (host port)
  (socket:make-socket :type :datagram :remote-host host :remote-port port))


(defun start-RS-client (server-hostname server-name)
  "Open a socket to a passive server."
  (let ((client-stream
         (make-UDP-socket server-hostname *port-for-RS-server*)))
    (cond (client-stream
           (setf (getf *RS-client-plist* server-name)
                 client-stream)
           (setf *default-RS-socket* client-stream)
           (values client-stream :ok))
          (T
           (values nil :server-open-failed)))))


(defun stop-RS-client (server-name)
  "Stops the named socket."
  (close (getf *RS-client-plist* server-name))
  (remf *RS-client-plist* server-name))


(defun stop-all-RS-clients ()
  "Stops all active RS sockets."
  (let ((servers nil))
    (do ((s *RS-client-plist* (cddr s)))
        ((endp s))
      (push (first s) servers))
    (dolist (s servers)
      (stop-RS-client s))))


(defparameter *system-initialized* NIL)


(defun shutdown-RS-system (server-name)
  "Closes the socket link..."
  (stop-RS-client server-name)
  (setf *system-initialized* NIL))


(defparameter *debug-uploaded-cmds?* NIL)


(defun UDP-socket-write (socket message)
  (if *debug-uploaded-cmds?*
      (print message)
      (socket:send-to socket message (length message))))


(defun UDP-socket-read (socket)
  (multiple-value-bind (message size host port)
                       (socket:receive-from socket 3000
                                            :buffer *RS-buffer*
                                            :extract t)
    (values message size)))


#|
> (defparameter *rs-1* (make-UDP-socket "localhost" 6000))
*rs-1*
> (UDP-socket-write *rs-1* "(init Scotties)")
15
> (UDP-socket-read *rs-1*)
"(init l 1 before_kick_off)

28
> (progn
    (dotimes (i 100) (UDP-socket-read *rs-1*))
    (UDP-socket-write *rs-1* "(sense_body)")
    (pprint (read-from-string (UDP-socket-read *rs-1*))))

(sense_body 0 (view_mode high normal) (stamina 4000 1)
 (speed 0) (kick 0) (dash 0) (turn 2) (say 0))
> (pprint (read-from-string (UDP-socket-read *rs-1*)))

(see 0 ((flag c b) 12.2 -25 0 0) ((line b) 10.8 -86))
> (UDP-socket-write *rs-1* "(bye)")
5
> (pprint (read-from-string (UDP-socket-read *rs-1*)))

(see 0 ((flag c b) 12.2 -25 0 0) ((line b) 10.8 -86))
> (UDP-socket-write *rs-1* "(bye)")
5
> (close *rs-1*)
#<multivalent datagram socket closed, but was at */1993 @ #x20ef3a72>
>
|#

Now our connections to X-Plane require serious UDP bit munging...

Scott
From: Kenny Tilton
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F440D15.5070509@nyc.rr.com>
Scott A Douglass wrote:
>> The data I get back from a socket is a vector of numbers. They come from
>> the RoboCup soccer server, which was originally a Lisp project, so those
>> numbers are character codes of, god bless 'em, a sexpr:
>>
>>    "(init l 2 before_kick_off)"
>>
>> So I'd like to hand it to read, but (preemy opt) without making it into a
>> new string.
>>
>> I see read-from-string, but not read-from-vector. read-from-string won't
>> eat vectors (damn strong-typing!). I also looked for a way to make a
>> stream out of a vector, but did not find one.
> 
> 
> Hmmm... we interface our agents to RoboCup with code like...

Yeah, I totally whiffed on this, should have been passing a character 
array to receive-from from the get go. My code looks like yours, now, 
except I went with nil on extract. I'm desperate at this point, I'll 
make it T and see if it fools anybody.

The thing is, I am running the server on my same NT box as ACL, and I am 
juggling all the players and the coach from one process. But even just 
the coach or one player can somehow block the server. I can run just a 
sequence: send init, gather all the responses (nine), and have it work 
one time and then not the next. I'll get pack three or four messages and 
then nothing. Even if I sleep between messages or do an 
mp:wait-for-input-available with a non-zero timeout. If I code it to 
fall out of the read loop when the server falls silent, I can then kick 
off the read loop on the same socket and get the rest of the messages. 
If I lower the WinNT ACL priority (to "low") I do not block the server 
(or is it only once in ten? gotta recheck that).

You all coming to ILC 2003 for the RoboCup match? Glad to hear of other 
Lispniks doing RoboCup.

-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker
From: Scott A Douglass
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <5885402.1061469916@Moby.psy.cmu.edu>
> The thing is, I am running the server on my same NT box as ACL, and I am
> juggling all the players and the coach from one process. But even just
> the coach or one player can somehow block the server.

I've recently developed a prolog-like agent specification formalism for 
research purposes.  Last semester, I used it in a cognitive agent modeling 
course.  The formalism allows you to express agents in UML (Rational Rose). 
Model files from Rose are automatically read/translated into ACL/lisp. 
Agents are managed/inspected in ACL via a GUI.

The framework is deliberately generic; it has been used to situate 
behavior-based and contemplative agents in a number of virtual environments 
(RoboCup being one of them). In situations where agents are being situated 
in virtual environments not implemented in lisp, the framework gives each 
agent a private process.  With each agent having its own process and 
socket, I've not seen blocking problems while using ACL.

Unless you need to run players and coach on the same rig (in the same 
process), I'd recommend that you use an existing project to run the players 
and invest your time in the coach.  Players just run, dribble, kick, etc. 
There are players out there that have solved most of the low-level issues 
associated with these actions.  The coach assesses situation and sends 
instructions to players via the command language.  The coach is the really 
interesting agent...

> You all coming to ILC 2003 for the RoboCup match? Glad to hear of other
> Lispniks doing RoboCup.

We've just been through "The First RoboCup American Open" here at CMU...  I 
think that was enough for the time being.
From: Kenny Tilton
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F462C91.3060301@nyc.rr.com>
Scott A Douglass wrote:
>> The thing is, I am running the server on my same NT box as ACL, and I am
>> juggling all the players and the coach from one process. But even just
>> the coach or one player can somehow block the server.
> 
> 
> I've recently developed a prolog-like agent specification formalism for 
> research purposes.  Last semester, I used it in a cognitive agent 
> modeling course.  The formalism allows you to express agents in UML 
> (Rational Rose). Model files from Rose are automatically read/translated 
> into ACL/lisp. Agents are managed/inspected in ACL via a GUI.

OK, i think I saw a reference to your work in my RoboCup surfing.

> 
> The framework is deliberately generic; it has been used to situate 
> behavior-based and contemplative agents in a number of virtual 
> environments (RoboCup being one of them). In situations where agents are 
> being situated in virtual environments not implemented in lisp, the 
> framework gives each agent a private process.  With each agent having 
> its own process and socket, I've not seen blocking problems while using 
> ACL.

Everyone has their own socket, but everyone and the coach run in the 
same proces. I had a Linux guru here last night. he got me set up with 
the server under Linux. Better, but still getting blocked after a 
period. He fired up tcpdump (i think!) and we could see that the soccer 
server was sending everything. but on the receive side the acl socket 
could stop finding new messages. but then it falls out to the repl and I 
kick off a fresh sequence of reading and it finds them!  Programming!! <g>

The really strange thing is that running db-sockets under cmucl I get 
/worse/ behavior! I gotta think I am doing something somewhere that 
really is a severe non-no in its interaction with sockets.


> 
> Unless you need to run players and coach on the same rig (in the same 
> process), I'd recommend that you use an existing project to run the 
> players and invest your time in the coach.  Players just run, dribble, 
> kick, etc. There are players out there that have solved most of the 
> low-level issues associated with these actions.  The coach assesses 
> situation and sends instructions to players via the command language.  
> The coach is the really interesting agent...

Yes, I see some fine players out there. But our Mission Statement is to 
do RoboCup with Lisp, as a way of attracting more people (RoboCuppers) 
to Lisp. And I have gotten quite interested in seeing if I can get a 
player to learn to dribble by itself, without sitting down with the 
soccer server doc and the math and physics handbooks and doing it that 
way. I want to give it a way to score its success and then just leave it 
running for a night and wake up to find it dribbling like Pele. :)

Too bad I am stuck on sockets. Anyway, thanks so much for your input. It 
is helping me reduce the search space.


-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker
From: Scott A Douglass
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3807424.1061558327@Moby.psy.cmu.edu>
> Everyone has their own socket, but everyone and the coach run in the same
> proces.

Sockets are a hoot :)  Using Mac/MCL they don't block and you need to 
poll...  Using PC/ACL they block and you need to carefully design control 
code.

I find giving each agent its own socket/process lets ACL's scheduler do all 
the work.  When a specific agent's socket blocks, it's process quietly 
makes way for the others.  Another benefit is that you can inspect/monitor 
agents at runtime (GUI-based agent inspectors are like a narcotic).

> The really strange thing is that running db-sockets under cmucl I get
> /worse/ behavior!

Right.  CMUCL has "inadequate" thread support and I've had problems with 
lockout too.  A research programmer I know working on another project (an 
environment for our cognitive architecture) has found that an occasional 
call to sleep breaks the logjam.

> Yes, I see some fine players out there. But our Mission Statement is to
> do RoboCup with Lisp, as a way of attracting more people (RoboCuppers) to
> Lisp.

Fair enough.  Not many of my students see the utility of lisp though--they 
prefer "plug&chug" languages where everything is in someone else's library. 
Only the sharpest students see that lisp allows them to massively leverage 
with meta-linguistic abstraction.  I hope you achieve mission success :)

> And I have gotten quite interested in seeing if I can get a player
> to learn to dribble by itself, without sitting down with the soccer
> server doc and the math and physics handbooks and doing it that way. I
> want to give it a way to score its success and then just leave it running
> for a night and wake up to find it dribbling like Pele. :)

If you're willing...  I'd enjoy seeing your final effort.
From: Kenny Tilton
Subject: Re: Streams, sockets, vectors, read...easier way?.
Date: 
Message-ID: <3F4670AA.9020608@nyc.rr.com>
Scott A Douglass wrote:
>> Everyone has their own socket, but everyone and the coach run in the same
>> proces.
> 
> 
> Sockets are a hoot :)  Using Mac/MCL they don't block and you need to 
> poll...  Using PC/ACL they block and you need to carefully design 
> control code.

Oh, i contacted Franz and they said use:

    (mp::wait-for-input-available (udp-socket rcs) :timeout 0)

returns nil if no input, so you do not have to do a blocking read.

> 
> I find giving each agent its own socket/process lets ACL's scheduler do 
> all the work. 

been thinking about that. right now, tho, I can see the problem with 
just one socket.


>> The really strange thing is that running db-sockets under cmucl I get
>> /worse/ behavior!
> 
> 
> Right.  CMUCL has "inadequate" thread support and I've had problems with 
> lockout too.  A research programmer I know working on another project 
> (an environment for our cognitive architecture) has found that an 
> occasional call to sleep breaks the logjam.

I'll try it over there. Didn't help under ACL, but I should see if it 
helps under cmu.

> 
>> Yes, I see some fine players out there. But our Mission Statement is to
>> do RoboCup with Lisp, as a way of attracting more people (RoboCuppers) to
>> Lisp.
> 
> 
> Fair enough.  Not many of my students see the utility of lisp 
> though--they prefer "plug&chug" languages where everything is in someone 
> else's library. Only the sharpest students see that lisp allows them to 
> massively leverage with meta-linguistic abstraction.  I hope you achieve 
> mission success :)

thanks. I guess our marketing plan is to go for the early adopters 
looking for a Better Way, including letting the ones who appreciate Lisp 
know it is an option again. They can build the stuff for others to 
plug&chug.

> If you're willing...  I'd enjoy seeing your final effort.

Absolutely. I am going to disengage from this socket battle and go lick 
my wounds, work on the client under ACL/NT with the priority down. When 
I have a world model to work off, I will put the source up on my new 
SourceForge project, RoboCells. It will work off another SF project I am 
resurrecting, Cells. The code will compile cleanly under ACL, LW, CLisp, 
CormanLisp, CMUCL and MCL, but god knows where the sockets can be made 
to work (WinNT with lower priority, at least, most of the time).

The bloke who dropped by last night is strong on Linux and keen on 
machine learning, but new to Lisp. I am hoping he will lean on the 
socket problem and save my butt.

:)


-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker