I’ve learned a bit about C/S. Should we apply it to our Robot World? It’s about Joy, dammit!

I say “learned”. Probably what I mean is that I’ve worked through a couple of examples, and have a general understanding of how a very simple, pretty simple, and not unreasonably complicated client-server arrangement might be done. I do not claim that I could just sit down here and type one in without a lot more learning. But I think I get the drift. I might summarize what matters to me, in the light of the robot program, this way:

  1. Sockets can be used to send messages back and forth reasonably reliably;
  2. Messages need to be of known length, either predefined or self-describing;
  3. JSON looks to be a decent scheme for sending structured information back and forth.

Now the fact is, I already “knew” those thing before I started this series on client-server. You can’t hang out with the kind of people I hang out with and not know that much. But now, unlike a couple of weeks ago, I’ve done it. (I have also done a few web-scrapers and elementary server objects in my checkered past.)

So now the questions before us include:

  1. When, if ever, should we build a real C/S arrangement for the Robot World?
  2. Given our current separation of concerns, what additional concepts and objects might we need?
  3. What message structure might we pick, providing a simple form combined with the ability to grow?
  4. How much of all this do we want to build?
  5. Why? What purpose does all this serve?

There are surely more questions, separate from these, and in the crevices between these. These will suffice.

Let’s think a bit more about these, and whatever thoughts they may evoke.

Why? Purpose?
The thousands of articles1 on this site tell us that I can find something to write about in any program anywhere. The original reasons for doing this particular one seem not to have materialized. We do not have the time and energy to work together to build a common example. Whatever we may write up separately will serve the intended readers well enough. The language we’re using does not suit all the team members, and when it comes to joy projects, that’s important.

My purpose in this ongoing screed is mostly personal: I enjoy expressing ideas in code. I enjoy solving problems. I enjoy learning, time and again, what works well for me and what does not. I enjoy writing about my discoveries. I enjoy the fact that a few people read and seem to enjoy what I write.

And I do it to occupy and exercise my mind. I do it to keep the dark thoughts of an octogenarian at bay.

I do it because it’s fun. It’s an ongoing activity, hobby, exercise … it’s an ongoing joy project.

As such, I work on things while they interest me, I work on the aspects that interest me, and I abandon a project when it no longer pleases me. This is the great privilege that I have: I can work on whatever I wish, and rarely need to do anything that I don’t want to.

Fun. Joy. Pleasure. And a bit of audience.

How Much to Build?
Since I’ve given up any real belief that this will ever turn into the public coding exercise we originally contemplated, there are perhaps only two reasons to do anything with it: I might see a question of interest, or someone in the audience might question whether something in the original promise, or the implications of what we have, could be done.
What Do You Mean By That?
It is my position that with a decent design sense and a reasonable level of focus on keeping our design quality up, we can proceed to build a program very incrementally, and that we are very unlikely ever to program ourselves into a corner that we can’t program back out of. I work with far less design planning than reasonable people would propose, to discover what happens, and to discover how easy or difficult it is to get the program to the state we want, the deliver the features that we want.

The current client-server exercise was undertaken because one of my colleagues felt strongly that what we had in this program absolutely needed client-server Right Now. I held, and still hold, that what we have is able to be made into a client-server app whenever we choose to. And, over more time than I’d like it to have taken, I was able to untangle the client side objects from the server side objects.

The current program has a very solid line between the “world” side and the “bot” side, communicating with very simple messages specifying what entity is to be controlled, and which of a small set of primitive operations it should perform. It’s quite ready for C/S if I wanted to do it. I consider it obvious, now, that we can make the program C/S if we want to.

So, from my viewpoint, the challenge: “You’ll never be able to get this thing into client-server mode” has been met. It should be clear to an observer that it’s down to nothing but the kind of work we know how to do. No more mysteries, mo more big concerns.

The Rest is Detail
So, from the viewpoint of my core position, which is that with a reasonable design sense and refactoring ability, we can evolve our program as needed, client-server is no longer a viable objection. I’d bet a large sum that I could do it, subject only to the possibility that I could keel over tomorrow and all bets would be off.
Learning is Everywhere
I have no doubt that the kind of evolution-driven development and writing I do would find meat to write about if we do go forward with more in this area.

In particular, I think we’d want to devise a message format that can handle multiple bots in a batch. It should allow for creation of new bots as well as commanding existing ones. That would probably mean that, on the client side, we would need some kind of notion of “cohort”, a collection of all the bots we’re operating. Would this be a big deal? Not likely. A simple collection would almost do the job, though a smarter object would probably be helpful.

On the server side, we’d need little more than an object to pull in the message and unwind it, and an object to build up the responses. It seems almost certain to me that the response would just be a corresponding collection of “knowledge” objects, which are already essentially a dictionary of mostly simple properties. I think batching would entail little more than building collections and spinning through them.

But But But
I see no substantial prospect of ever deploying the World side as an actual server.
And And And
There are probably some really interesting problems in Bot collaboration that we could be addressing. They already deal with sorting blocks together by scent2. What if they also need food, a different kind of object in the world? What if each bot has a food supply that it needs to replenish? What if a bot that is running low on food could be helped by a bot that had enough to share? What if bots gave off pheromones signifying various aspects of their lives?

Did you know that a dog can scent a gradient? It can determine that the scent is stronger up the path than down the path. What if each cell in the world held a number of directed scents, scents that had a value and a direction indicating either where a static object might be, or the direction a bot was moving when it went through the cell?

Could we give our bots very simple logic, when working and not laden, walk upstream toward block scent, or follow the scent of other worker bots, leaving your own worker scent behind. When laden, follow the scent of other laden bots. Might rules like that create paths through the world, routes between interesting locations? Might they cause the bots to have significant intelligent-seeming behavior, while each bot really only followed very simple rules?

Digression

We already have very complex results from very simple behavior. Here is the complete decision logic of a bot:

class Walking:
    def action(self, _knowledge):
        return []

    def update(self, knowledge):
        knowledge.gain_energy()
        if knowledge.has_energy():
            if knowledge.has_block:
                return Laden()
            else:
                return Looking()
        return Walking()


class Looking:
    def action(self, knowledge):
        if knowledge.can_take:
            return ['take']
        return []

    def update(self, knowledge):
        if knowledge.has_block:
            knowledge.use_energy()
            return Walking()
        else:
            return Looking()


class Laden:
    def action(self, knowledge):
        if knowledge.has_energy():
            if knowledge.can_drop:
                return ['drop']
        return []

    def update(self, knowledge):
        if knowledge.has_block:
            return Laden()
        else:
            knowledge.use_energy()
            return Walking()

There is a tiny bit more logic in the notion of whether we can take or drop a block:

    @property
    def can_take(self):
        is_scent_ok = self._scent <= self.take_threshold
        return is_scent_ok and self.vision.match_forward_and_one_side('B', '_')

    @property
    def can_drop(self):
        vision_ok = self.vision.match_forward_and_one_side('_', 'B')
        scent_ok = self._scent >= self.drop_threshold
        return vision_ok and scent_ok

We can take a block if the scent around it is not too strong, and it has a space on at least one side of it.

We can drop a block if the scent around it is large enough, and there is a block on at least one side of where we plan to drop it.

That’s it. Blocks have different aromas, and when we are carrying a block of a given aroma, that’s the aroma we pay attention to.

The result of that behavior is that the bots, working absolutely independently, gather stones together, in piles of the same aroma:

blocks arranged by color (aroma)

I think that’s fascinating, and a lot more fun than programming Yet Another Messaging Scheme.

But I Digress

What will we do next? I’m not going to commit to a decision today, and anyway, if I decided today I wold not hesitate to change that decision tomorrow. I won’t call that “Agile”: I may never call anything “Agile” again.3 So, no promises.

However, I think I could benefit from actually doing a bit more client-server work, working out a structure that appeals to me more than the scheme from the (excellent) RealPython tutorial that I’ve followed in the preceding half-dozen or so articles. So I am leaning a bit in the direction that might lead to steps like:

  1. Devise an object representing a batch of commands;
  2. Build a structure on the client side calling for a batch, probably a Cohort object;
  3. Devise a socket-oriented message format, simpler than the one in the tutorial;
  4. Use that format, JSONing and deJSONing it, between the Bot/Cohort side and the World side;
  5. Maybe, just maybe, do a localhost C/S connection just to prove, I don’t know, something.

Those steps are numbered, but they don’t really need to be done in that order. For example, on a given day, we could do something like this sequence:

  1. Build a message object that computes its length and puts it on the front;
  2. Test some socket-oriented code, using fake objects like yesterday’s, to read and write that format;
  3. Change whatever the command list is now to be compatible with the above format, if it isn’t already;
  4. Use the command list in the Game code, which already runs multiple bots;
  5. Call it close enough.

The point is, and it is not impossible that I do have one, we can pick up almost any of a large number of stories, in almost any order, and start there, and build toward the big picture.

In these articles, sometimes I choose odd points to start, just to see whether we ever get in real trouble, and to learn from that trouble. Sometimes I choose things that are fun.

I’m here for the joy, and to share the joy of building Some people build furniture, make knives, or play music. I write programs and articles. I hope that someone else enjoys them and benefits somehow. If they do, I enjoy hearing back from them. And, hearing back or not, I enjoy what I do, and wish you enjoyment in what you do.

See you next time … if you think you’ll enjoy it!



  1. There are almost 6000 “objects” making up my web site. I suppose some of those are folders, and each article has its own, but even so there must be 2500 or more articles in here. How many have you read? I’ve read them all! 

  2. “A time to gather stones together.” 

  3. But that, too, would be a decision and subject to change.