writing the game while playing it

26 views
Skip to first unread message

Curt Siffert

unread,
Dec 9, 1998, 3:00:00 AM12/9/98
to
What would it take to be able to add on to your
IF game while playing it?

I'm thinking something like an interpreter where
you can play the game but also set your flags,
create new ones, fashion a new room, new objects,
new flags, just kind of build as you go. At any point
you could do a code dump of (say) Inform.

And then when you wanted to declare it done, it
would freeze it as-is and output compiled zcode.
No need for it to be zcode first.

In a way that's kind of like those old LPmuds, I
guess. But I like text adventure games better.
Even if this were only used to make frameworks
while the real advanced stuff would be done by
editing the actual code.

Possible?

Crut


Jeff Hatch

unread,
Dec 9, 1998, 3:00:00 AM12/9/98
to
Curt Siffert wrote:

There's been some talk here about this before -- look for discussions of
"god mode" on Deja News.

As far as I can remember, the problem is that statically compiled
languages like Inform and TADS don't let you really interact with your
additions in ways that aren't foreseen by the "god mode" designer. For
instance, it's easy to make it so that you can keep adding simple rooms
as you explore your game, but if you create a puzzle with complex code,
you won't be able to test it until you stop to recompile the code.

One simple way to get around this might be to create a "god code"
command in a special zcode interpreter that automatically saves a game's
input script, recompiles the game, and re-executes the input script.
(Randomization would have to be deactivated.) That'd be time-consuming
yet reasonably effective.

AFAIK every authoring system currently available is either statically
compiled or too simple to be much use for a complex project, so this
appears to me to be the best workaround. It's possible to create an
interpreting compiler for any language, but the amount of labor involved
would be roughly comparable to the work of creating a new compiler,
which few people are eager to do.

-Rúmil

Norman Ramsey

unread,
Dec 12, 1998, 3:00:00 AM12/12/98
to
In article <366f23c0$0$2...@nntp1.ba.best.com>,

Curt Siffert <sif...@museworld.com> wrote:
>What would it take to be able to add on to your
>IF game while playing it?
>
>I'm thinking something like an interpreter where
>you can play the game but also set your flags,
>create new ones, fashion a new room, new objects,
>new flags, just kind of build as you go. At any point
>you could do a code dump of (say) Inform.

I'd love to have somebody come to UVa and do this as a masters'
thesis. The underlying technology of `incremental compilation' is
reasonably well understood, but there are some interesting questions
about just what state is destroyed when you add or change code.

Any takers?

Darin Johnson

unread,
Dec 12, 1998, 3:00:00 AM12/12/98
to
n...@labrador.cs.virginia.edu (Norman Ramsey) writes:

> I'd love to have somebody come to UVa and do this as a masters'
> thesis. The underlying technology of `incremental compilation' is
> reasonably well understood, but there are some interesting questions
> about just what state is destroyed when you add or change code.
>
> Any takers?

This seems like just an extension of existing MUDs, many of which
allow you to create and change the game on the fly, while playing it.

Two common techniques: the TinyMUD, MUSHes, MOOs and derivatives (all
derivatives of "monster" really) essentially have a database that is
extended at run time - creating an object, adding exits, adding
conditions to the exits, or possibly adding a chunk of code here and
there in advanced version, is just adding data to the database.
State is created and destroyed in a straightforward way.

The LPMud and some others (probably AberMUD), load up or compile
source code upon demand, placing the compiled objects into memory.
Builders can load up new source code during the game. It's not
incremental compilation, in that each file is completely compiled (in
the same way that compiling the individual C files one at a time is
not incremental compilation). State is not destroyed usually, as
changing the underlying code essentially makes multiple code copies
(all new objects get new behavior, old objects keep the old behavior).

--
Darin Johnson
Support your right to own gnus.

Sean T Barrett

unread,
Dec 13, 1998, 3:00:00 AM12/13/98
to
Darin Johnson <da...@usa.net.nospam> wrote:
>n...@labrador.cs.virginia.edu (Norman Ramsey) writes:
>> I'd love to have somebody come to UVa and do this as a masters'
>> thesis. The underlying technology of `incremental compilation' is
>> reasonably well understood, but there are some interesting questions
>> about just what state is destroyed when you add or change code.
>
>This seems like just an extension of existing MUDs, many of which
>allow you to create and change the game on the fly, while playing it.

>The LPMud and some others (probably AberMUD), load up or compile


>source code upon demand, placing the compiled objects into memory.

...


>State is not destroyed usually, as
>changing the underlying code essentially makes multiple code copies
>(all new objects get new behavior, old objects keep the old behavior).

A MUD system I was developing used a different tactic: reloading
a new definition for a class automatically caused all subclasses
and objects of that class to get the new behavior. This is far
more useful for obvious reasons (you don't have to 'recreate'
everything back in their initial states to test). However, as
the first poster was implying, this causes some extreme awkwardness.
What initial state will newly added properties/attributes have?
(You can't run the 'constructor' on old objects; you sort of need
a 'delta constructor' that fixes-up from the old version to the new.)
What if you get rid of a property/attribute from a class, should
it automatically remove them from descendents?

I didn't directly address these problems in the interpreter/compiler
core, I left it to the 'library' side to explore coding standards
to address this. The only core feature to support this was that
properties could be dynamically added to objects in a simple (in
fact, automatic way), so basically the first time you tried to use
the new functionality, it 'fixed itself up'.

It was fun, cool, and very powerful to do things this way, but
I never found a satisfactory way of dealing with the complications
of adding/removing state on changes. My read (although I could
be wrong) is that there really *isn't* one, as the definition of
'the right thing to do' could easily vary depending on the added
code.

Moreover, this approach to building seems far better suited to
muds, which are more dynamic, ongoing projects, which don't *have*
a well-defined 'start state' if they're creating a persistent
universe. Whereas for single-player, having big flat text files
representing the initial state of the IF seems to me to be
strictly superior.

Sean

David Given

unread,
Dec 13, 1998, 3:00:00 AM12/13/98
to
In article <F3vs7...@world.std.com>,
Sean T Barrett <buz...@world.std.com> wrote:
[...[

>>State is not destroyed usually, as
>>changing the underlying code essentially makes multiple code copies
>>(all new objects get new behavior, old objects keep the old behavior).
[...]

>It was fun, cool, and very powerful to do things this way, but
>I never found a satisfactory way of dealing with the complications
>of adding/removing state on changes. My read (although I could
>be wrong) is that there really *isn't* one, as the definition of
>'the right thing to do' could easily vary depending on the added
>code.

LambdaMOO gets round this by making all classes objects. So an object will
inherit all methods and properties from its parent; add a property to the
parent, and any instances will automagically receive it. The engine
distinguishes between properties that have been modified and properties
that have not been, so that the instance can change one of its properties
and the value is no longer inherited.

LambdaMOO's object system is generally excellent and I think that a custom
DB running in single-user mode would make a *superb* IF system. Especially
as it allows incremental game development.

--
+- David Given ------------McQ-+ Q: What's the difference between the US
| Work: d...@tao.co.uk | and Russia?
| Play: dgi...@iname.com | A: The US has a legal Communist party.
+- http://wiredsoc.ml.org/~dg -+

Jeff Hatch

unread,
Dec 13, 1998, 3:00:00 AM12/13/98
to
Norman Ramsey wrote:

> I'd love to have somebody come to UVa and do this as a masters'
> thesis. The underlying technology of `incremental compilation' is
> reasonably well understood, but there are some interesting questions
> about just what state is destroyed when you add or change code.
>

> Any takers?

I assume that what's well understood is the technology required to make
functions recompile appropriately, and get added into the game without
any need to make the game stop running?

As for state issues -- one practical method for text adventures is to
require the use of an integrated compiler/editor/game engine. When you
add a variable to a class definition, the compiler searches through an
editor-maintained lists of objects that belong to that class, and tells
them that they will need to have a little more room to store data now.
In many cases, objects will need to be reassigned to new memory
locations, and any games that are in memory will have to do a lot of
buffer copying. This means that every pointer to an object memory
address will need to be adjusted to point to a new data area. At this
point, if you're using a "strongly typed" language, you can simply
search the variable allocation chart to find all the variables that are
pointers to objects, compare them to the objects' old positions, and
move them if necessary. Since you're presumably between turns in the
game when you modify the program, you don't need to worry about altering
pointers on the stack. I haven't worried about dynamic permanent
storage yet. If you're using multiple inheritance, then now that the
class's object data area is a different size, some subclasses will need
to use different values to add to the pointers in order to do pointer
class conversions, and some subclass variables will be at different
offsets from their base pointer values. These conversions will be in
already-compiled code, so the most efficient way to allow this kind of
incremental compilation is to make pre-release compilation leave special
null-operation flags in the code that specify locations where code could
need to be changed. Then any incremental changes can cause a quick scan
through code to find any necessary modifications.

Is that the sort of stuff you're looking for?

-Rúmil

Norman Ramsey

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
In article <y1u3e6k...@acuson.com>,

Darin Johnson <da...@usa.net.nospam> wrote:
>This seems like just an extension of existing MUDs, many of which
>allow you to create and change the game on the fly, while playing it.

This is a good point; thanks for bringing it to my attention. Some of
these, like the MOO, have fairly powerful programming languages.

>The LPMud and some others... State is not destroyed usually, as


>changing the underlying code essentially makes multiple code copies
>(all new objects get new behavior, old objects keep the old behavior).

How do you keep players from interacting with old objects?


Part of my interest is trying to leverage the existing base of library
code and expertise associated with Inform. I'm curious, however, to
know if anyone has developed a serious game with the programmable
MUDs? Are there any good libraries?


Norman

Norman Ramsey

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
In article <367426EE...@hatch.net>, Jeff Hatch <je...@hatch.net> wrote:
>> I'd love to have somebody come to UVa and do this as a masters'
>> thesis. The underlying technology of `incremental compilation' is
>> reasonably well understood, but there are some interesting questions
>> about just what state is destroyed when you add or change code.
>
>I assume that what's well understood is the technology required to make
>functions recompile appropriately, and get added into the game without
>any need to make the game stop running?

What's well understood is how to recompile only code that has changed.
Linking the code into a running game is tolerably well understood.
Dealing with the states of objects (very important in an OO
framework, and closely associated with the code) is not, to my
knowledge, well understood.

>As for state issues -- one practical method for text adventures is to
>require the use of an integrated compiler/editor/game engine.

I think that's what I'm proposing someone build. But there are
significant advantages to making the source compatible with Inform,
and to supporting the emission of Z-code (or JVM-code, or TADS-code,
or P-code, or ...).

>[discussion about implementation detals]


>
>Is that the sort of stuff you're looking for?

I think that sort of stuff is relatively straightforward. I think the
interesting stuff is more oriented to the semantics of changing the
game while its running. The first thing that pops to mind is `what
should the state of an object be when its code changes?' What happens
to the object's existing state? I suspect the answers depend on *how*
the source code changed.


Norman

Sean T Barrett

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
David Given <dg@> wrote:
>Sean T Barrett <buz...@world.std.com> wrote:
>>I never found a satisfactory way of dealing with the complications
>>of adding/removing state on changes. My read (although I could
>>be wrong) is that there really *isn't* one, as the definition of
>>'the right thing to do' could easily vary depending on the added
>>code.
>
>LambdaMOO gets round this by making all classes objects. So an object will
>inherit all methods and properties from its parent; add a property to the
>parent, and any instances will automagically receive it. The engine
>distinguishes between properties that have been modified and properties
>that have not been, so that the instance can change one of its properties
>and the value is no longer inherited.

This is exactly what the system I was talking about (which,
indeed, predates LambdaMOO, and was developed at the same
time as plain old MOO (or was it called TinyMOO?)) did.

But it doesn't really address the problems I mentioned.
To get technical, a core problem is one of _maintaining
invariants_. If you have a class Y derived from X, Y
may attempt to maintain some invariant making use of state
from X. If X can change willy-nilly out from under it,
these invariants may not get maintained. Thus, the
problem is that even though you only change X, it isn't
necessarily even sufficient to have a custom 'how to update
from old X to new X' code, since this may not satisfy
Y's invariants.

Rather than try to give a meaningful example of an invariant,
I will give you an incredibly simple example of a very closely
related problem which comes up over and over again in the
commercial computer games that I've worked on. This example
is intentionally non-IF, simply because it's pretty much the
simplest example I can think of. You will just have to take
my word for it that similar problems can arise in MUDs (although
I don't know about single-player IF).

Suppose I define a 'generic' Orc type. I populate my area
with three or four orcs. By default, orcs have 20 hit points.
Then I customize one particular orc to make it tougher, giving
it 30 hit points. (So it is marked as having 'changed', much
as you describe LambdaMOO supporting above.)

Now, after playing for a while, I determine that the orcs
are too easy, so I change the 'generic' Orc type to have 40 hit points.
Oops, now that one I customized still only has '30' because my
system noticed I had customized it and therefore didn't update
it.

But suppose it *did* update it anyway. What should it set it
to? Should it be 50 hit points, assuming I meant '+10 over default'?
Or should it be 60 hit points, assuming I meant '50% extra'?
Or perhaps I had customized it to '((old/5)^2-1)*2', in which
case it should now be 126 hit points.

(Sure, I can go update it by hand, but this problem can
occur with thousands of orcs, and it can occur where the 'customized'
thing is itself a class. It breaks modularity by requiring all
things dependent on this class in the hierarchy having to be
tweaked by hand.)

The problem in this particular case is that the semantics of
the changed version aren't explicit anywhere but in my head,
so the system can't guess it. So the problem I was describing
originally is that of determining how to make this sort of thing
explicit to the system--i.e. represent it in code, generically,
without it being a giant bruden on the developer.

I promise you, it's really honestly not something that can
be solved as simply as your characterization of LambdaMOO.

Sean

Jeff Hatch

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
Norman Ramsey wrote:

> What's well understood is how to recompile only code that has changed.
> Linking the code into a running game is tolerably well understood.
> Dealing with the states of objects (very important in an OO
> framework, and closely associated with the code) is not, to my
> knowledge, well understood.

Okay, that's basically what I thought you were saying.

> I think that's what I'm proposing someone build. But there are
> significant advantages to making the source compatible with Inform,
> and to supporting the emission of Z-code (or JVM-code, or TADS-code,
> or P-code, or ...).

Yes, and significant disadvantages, too.


> I think that sort of stuff is relatively straightforward. I think the
> interesting stuff is more oriented to the semantics of changing the
> game while its running. The first thing that pops to mind is `what
> should the state of an object be when its code changes?' What happens
> to the object's existing state? I suspect the answers depend on *how*
> the source code changed.

Actually, that seems fairly straightforward to me, too. For instance, suppose I
made a PianoBench that I could sit on, and now I make it an OpenableContainer
also. All the state information for a default OpenableContainer will then be
added to the Bench, so it's now closed and contains nothing. In an integrated
compiler/editor/game engine, it's easy to make it possible to edit object state
directly, so if I want it to be open by default, no problem. Then if I take away
the fact that it's a Supporter, the old information saying what was on it is
thrown away. This seems pretty simple -- can you give me an example of a more
confusing situation, where there are different ways that an editor might be able
to handle a change in object code?

(Obviously, my example uses a typical C-like language, not Inform.)

-Rúmil


David Given

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
In article <F3xsJ...@world.std.com>,

Sean T Barrett <buz...@world.std.com> wrote:
[...]

>Suppose I define a 'generic' Orc type. I populate my area
>with three or four orcs. By default, orcs have 20 hit points.
>Then I customize one particular orc to make it tougher, giving
>it 30 hit points. (So it is marked as having 'changed', much
>as you describe LambdaMOO supporting above.)
>
>Now, after playing for a while, I determine that the orcs
>are too easy, so I change the 'generic' Orc type to have 40 hit points.
>Oops, now that one I customized still only has '30' because my
>system noticed I had customized it and therefore didn't update
>it.
[...]

Ah. I see what you mean now.

Well, in this particular situation (a repopulating dungeon), then the
obvious thing to do is to be specific in your spawning routine:

o := create(Orc);
o.hitpoints := o.hitpoints + 20;

But this wouldn't work in the general case.

[...]


>(Sure, I can go update it by hand, but this problem can
>occur with thousands of orcs, and it can occur where the 'customized'
>thing is itself a class. It breaks modularity by requiring all
>things dependent on this class in the hierarchy having to be
>tweaked by hand.)

Well, all I can say is that I never found it a problem.

--
+- David Given ------------McQ-+ "If you're up against someone more intelligent
| Work: d...@tao.co.uk | than you are, do something insane and let
| Play: dgi...@iname.com | him think himself to death." --- Pyanfar
+- http://wiredsoc.ml.org/~dg -+ Chanur

Darin Johnson

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
n...@labrador.cs.virginia.edu (Norman Ramsey) writes:

> >The LPMud and some others... State is not destroyed usually, as
> >changing the underlying code essentially makes multiple code copies
> >(all new objects get new behavior, old objects keep the old behavior).
>
> How do you keep players from interacting with old objects?

You don't. (the players themselves are old objects :-).
There were some drawbacks, but not much. As soon as the game
restarted, everything was new again. (note: unlike the tiny muds and
derivatives, the game state is not normally saved between games)

I think it was done this way because one, it was simpler, and two, you
don't have to worry about calling an updater method in each object (a
royal pain if the updater method in some objects had a bug, and the
simple recompile of a basic class caused the entire mud to crash).

The drawbacks are few really. If updating everything was necessary,
you just told everyone to get off and rebooted, or you hunted down all
the old versions and junked them. (some of the muds had extremely
short uptimes, sometimes even measured in hours instead of days)

> Part of my interest is trying to leverage the existing base of library
> code and expertise associated with Inform. I'm curious, however, to
> know if anyone has developed a serious game with the programmable
> MUDs? Are there any good libraries?

Some of the libraries are good, but oriented towards multi player
games. The biggest drawback, is that most muds have really poor
parsers compared to TADS or Inform. Parsers are major cpu hogs, and
when you have 30+ players logged in typing as fast as they can, a full
blown parser is too expensive. TADS and Inform are vastly better
choices for single player standalone games (I used to want to build a
mud with a nice language and model like TADS, but no time or energy).

--
Darin Johnson
Luxury! In MY day, we had to make do with 5 bytes of swap...

Darin Johnson

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
buz...@world.std.com (Sean T Barrett) writes:

> If X can change willy-nilly out from under it,
> these invariants may not get maintained. Thus, the
> problem is that even though you only change X, it isn't
> necessarily even sufficient to have a custom 'how to update
> from old X to new X' code, since this may not satisfy
> Y's invariants.

A simple example would be vectors. If you have a lot of vectors
loaded that use X-Y coordinates, and then you change the class to have
use angle-distance, you've got a problem. Not only has the code
changed, but the variables inside the object have to change as well
(ie, delete 2 variables, add 2 variables, and initialize the new state
according to the old state).

Now lets get more subtle. What if all that changes is an invariant.
Lets say we have a lit candle in a bag. The code never bothered to
disallow this. But the player is walking around with it anyway. Now
the designer (who may or may not be the player) decides to add an
invariant that "candle inside bag ==> unlit candle". What happens?
All sorts of wierd things could happen perhaps. If the candle should
be extinguished, how is this determined? If the candle is left alone,
then the system is out of wack with the invariants (ie, bugs may start
cropping up).

An analogous problem is save-game files. These are just snapshots of
the game's state. Ie, to solve these state problems, one could always
just save the game, recompile, restart, and reload the save game.
However, the save game may not be able to be reloaded. Ie, we've
added/removed variables, invariants changed, units of measurement have
changed, etc.

So, I suppose that if you solve the problem for save-game files, then
you solve it for the dynamic editing of the game too.

--
Darin Johnson
Gravity is a harsh mistress -- The Tick

David Glasser

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
Sean T Barrett <buz...@world.std.com> wrote:

> Suppose I define a 'generic' Orc type. I populate my area
> with three or four orcs. By default, orcs have 20 hit points.
> Then I customize one particular orc to make it tougher, giving
> it 30 hit points. (So it is marked as having 'changed', much
> as you describe LambdaMOO supporting above.)
>
> Now, after playing for a while, I determine that the orcs
> are too easy, so I change the 'generic' Orc type to have 40 hit points.
> Oops, now that one I customized still only has '30' because my
> system noticed I had customized it and therefore didn't update
> it.
>

> But suppose it *did* update it anyway. What should it set it
> to? Should it be 50 hit points, assuming I meant '+10 over default'?
> Or should it be 60 hit points, assuming I meant '50% extra'?
> Or perhaps I had customized it to '((old/5)^2-1)*2', in which
> case it should now be 126 hit points.

Hm. My best guess would be allowing you to set the hitpoint field to a
expression which can access the object's base classes. If you typed in
'30', it would always be thirty, but you could do 'Orc + 10' or
'((Orc/5)^2-1)*2' if you wished.

Not that this would be trivial or anything.

--
David Glasser gla...@NOSPAMuscom.com http://onramp.uscom.com/~glasser
DGlasser @ ifMUD : fovea.retina.net:4001 | r.a.i-f FAQ: come.to/raiffaq
Sadie Hawkins, official band of David Glasser: http://www.port4000.com/

Curt Siffert

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to

Norman - care to answer a few digressing questions?

I'm asking you because I noticed you were a faculty
member at a University that must frequently deal with
graduate students. I've got an undergraduate degree
and want to get back to academia after three years in
Silicon Valley. I've got some specialized interests and
am trying to find a graduate program that would be a
good fit for me.

Up for a bit of free advice-dispensing and brainstorming
if I gave you a fuller description of the kind of things I'm
interested in pursuing? (Some of it is relevant to the IF
discussion.)

Thanks!
Curt Siffert

Norman Ramsey wrote in message <74uurn$abo$1...@murdoch.acc.Virginia.EDU>...


>In article <366f23c0$0$2...@nntp1.ba.best.com>,
>Curt Siffert <sif...@museworld.com> wrote:
>>What would it take to be able to add on to your
>>IF game while playing it?
>>
>>I'm thinking something like an interpreter where
>>you can play the game but also set your flags,
>>create new ones, fashion a new room, new objects,
>>new flags, just kind of build as you go. At any point
>>you could do a code dump of (say) Inform.
>

>I'd love to have somebody come to UVa and do this as a masters'
>thesis. The underlying technology of `incremental compilation' is
>reasonably well understood, but there are some interesting questions
>about just what state is destroyed when you add or change code.
>

>Any takers?

Darin Johnson

unread,
Dec 14, 1998, 3:00:00 AM12/14/98
to
gla...@DELETEuscom.com (David Glasser) writes:

> Hm. My best guess would be allowing you to set the hitpoint field to a
> expression which can access the object's base classes. If you typed in
> '30', it would always be thirty, but you could do 'Orc + 10' or
> '((Orc/5)^2-1)*2' if you wished.

But you still don't know what is wanted. Ie, was the one orc set
to 30 because it was supposed to be larger than the other orcs, or
was it set to 30 because there was no weapon that could do that much
damage, etc? Essentially, the compiler does not have any way to know
without getting some info from the programmer.

Note that if you're just editing a normal set of source code, you just
make sure you update all orcs when you change how orcs work; if you
don't, then it's a bug. The difference in a dynamic system is that
you will have a lot of objects that aren't explicitly mentioned in
source code (ie, database instances, or dynamic clones).

--
Darin Johnson
"Floyd here now!"

Lucian Paul Smith

unread,
Dec 15, 1998, 3:00:00 AM12/15/98
to
Sean T Barrett (buz...@world.std.com) wrote:

: Suppose I define a 'generic' Orc type. I populate my area
: with three or four orcs. By default, orcs have 20 hit points.
: Then I customize one particular orc to make it tougher, giving
: it 30 hit points. (So it is marked as having 'changed', much
: as you describe LambdaMOO supporting above.)

: Now, after playing for a while, I determine that the orcs
: are too easy, so I change the 'generic' Orc type to have 40 hit points.
: Oops, now that one I customized still only has '30' because my
: system noticed I had customized it and therefore didn't update
: it.

Suppose, instead of focusing on what the non-generic instances 'meant'
when they varied from the norm, you focused instead on what the *change*
meant. In other words, in this example, why are you giving Orcs more hit
points? Did you want them to be 10 points better or 100% better? Or 50%
better plus a basic 5 points?

This wouldn't solve, for example, the problem of a specific orc having a
*routine* that determined its hit points, but perhaps it brings you one
step closer to a generic solution for updates.

-Lucian

Reply all
Reply to author
Forward
0 new messages