[Twisted-Python] pb.Copyable, round trip objects, and untrusted clients

Jasper Phillips jasper at peak.org
Sun May 23 00:36:42 EDT 2004


On Sat, 22 May 2004, David Ripton wrote:

> Jasper Phillips wrote:
> 
> > I'm treating event history as game state, although I haven't implemented it
> > yet.  Not so much for the AIs use, but to model it's effects on future
> > events.  IMHO treating it as game state is also a simpler model.
> 
> So future events depend on the exact sequence of events used to reach 
> the current state, not just the current state?  That sounds expensive.

Well, in theory they could, but in practice they can depend upon simpler
things, such as if two nations have ever been at war, how long ago was the
war, and how was it resolved.  I'm considering filtering past events and
Just storing those aspects that events switch on in a condensed format; e.g.
storing time since last war instead of whether there was war for each turn.

However, even this simpler approach is fairly complex, and is a prime target
for the feature axe...


> > IMHO this seems overly complex.  I don't like maintaining parallel objects
> > or parallel calculation, as it smells like ClientGame/ServerGame...

[snip]
> Having separate *objects* of the same classes on the two sides is fine, 
> though.  In fact, in a game with hidden information, it's inevitable. 
> The server Game object will hold the full state, and each client's Game 
> object will hold a subset.  This is true whether the server sends 
> censored copies of its state to clients, or whether it sends them 
> subsets of the full event stream and lets clients generate their own 
> censored copies.

True, so long as they're the same objects.  I still don't like
reconstructing them in parallel.  It seems error prone when combined with
hidden state, and doesn't allow for outcomes based upon hidden state
(although this is not a problem for Titan).


> > I disagree that sending objects isn't practical, IMHO it just helps to
> > approach it slightly differently.  I'll try to explain what I mean by
> > roughly describing my game as an example;  if my design is crappy please
> > feel free to shoot holes in it! :-)
> > 
> > Much of my game's logic is based upon Copyable Actions which are used by
> > both Server and Client, e.g. MoveAction.  These have a .__call__(state)
> > which modifies the passed state as they see fit, as well as a
> > .validate(state) to ensure a move is legal.  Players create a list of such
> > Actions, and pass them to the Game server as their turn.  
> 
> Standard command pattern, but cleaner in Python because of __call__.
> 
> Do your turns have phases, requiring certain actions to occur at certain 
> times?

There is a distinct sequence of events, with certain types of actions being
resolved before others.  This is handled by a TurnTask, who's job it is to
run all the Actions, and resolved conflicts between them.  It embodies the
customary phase order of boardgames.

> Can other players interrupt your turn with actions, or are their replies 
> (e.g. strikebacks to your attacks) completely automated or deferred 
> until their turns?

My game has simultaneous turns, classical Diplomacy style.  There are some
twists that allow reactions, but these are simultaneous as well.

> > With only literal args these Action objects can be passed safely to the
> > game, which will reconstitue it's own versions, validate them, then
> > invoke them by passing in it's True State.  Players are given their own
> > PlayerState view of TrueState each turn, with real (copies of) objects
> > they can use for display, UI and validation.
> 
> It seems that only sending game state updates once per turn would reduce 
> interactivity too much.  I want to see my opponents' (visible) moves as 
> they happen, not batched up at the end of his turn.  Beware of 
> sequential solitaire.

This is just a matter of semantics.  A Turn in my engine can be whatever you
want, for example each of a players moves in Titan could be a "Turn", with
updated state passed to all players after each one.  I prototyped the
Boardgame Binfa, which worked just like this.

> PlayerState / TrueState sounds like the ClientGame / ServerGame problem 
> I was warning about.  It's not necessarily bad if they have the same 
> interface and PlayerState just has a subset of the data, but look out 
> for duplicate code.

PlayerState is just a subset of TrueState, but with methods for determining
just what subset.  Methods that accept one accept the other, most notably
Action.validate().


> > IMHO Making all of this essentially part of the API is cleaner than having
> > bulk "Reconsitute Objects" methods.
> 
> Yes.  Having direct support in PB for the idea of const (copy this 
> object when I send it, but ignore any changes that were made to it on 
> the other side if I get it back), so that you don't have to do any of 
> this, would be even cleaner.  I don't know if there's much demand for 
> this feature from other people, though.

I suspect the mechanism necessary to specify the key field for these "const"
objects and where to find them would be as complex as just having clients
reference them by id, yet perhaps less clear.


> Anyway, I'm looking forward to seeing your game at some point.

I've got most of the core work done along with much of the game mechanics
and GUI, but not much game specific content.  I'll be done some time next
year, hopefully earlier than later.  When I have enough to start contracting
artists I'll start a website and stick it in my .sig, probably sometime in
the next several months.

I'm pondering LGPL'ing the underlying game framework (based on Twisted and
Pyui) at this time as well, although this is a fair amount of hassle and I'm
not sure anyone's interested.

-Jasper





More information about the Twisted-Python mailing list