On Thu, 29 Jun 2000, Patrick Dughi wrote:
> Basically, a pair of set/accessor functions for each character part,
> based on idnum lookup? Sounds a bit annoying.
In non-OO languages that don't support exception-handling? Very annoying.
In OO languages that do support exception-handling? Probably not that
much better. Compare the following in C,
/*
* C: get_char_gender() looks up the pointer through some means
* and returns it gender -- or -1 if we have an error.
*/
byte sex = get_char_gender (cid);
if (sex == -1) return;
sprintf (buf, "It's a %s.\r\n", HIMHER (sex));
send_to_char (buf, to);
// C++: A CharacterID class is at work, here. It has a private(?)
// function named character() inside of it that fetches the
// character pointer. If it fails to fetch the pointer, it
// throws a BadCharacter exception. All of its accessors use
// the character() function, so they all throw.
try
{
to.writeLine ("It's a %s.", HIMHER (cid.gender()));
}
catch (BadCharacter* bc)
{
delete bc; // ?
return;
}
In this minimal example, the C code seems much better. However, the
exception handling mechanism permits us to only handle an error once, not
every time it might occur:
try
{
for (int hits = 0; hits < numHits; hits++)
{
.
. // Calculate the damage amount
.
fighting ().character ()->damage (this, amount);
}
}
catch (BadCharacter* cd)
{
fighting (NOBODY);
writeLine ("Congratulations, you won!");
}
It's still really ugly, but imagine having to write a pointer-free version
of act() using the C mechanism demonstrated above. The error checking in
each case...break block would be more than enough to drive me completely
mad. OTOH, both versions could get away with,
struct character_data *ch = get_char_by_id (cid);
.
.
.
if the code is guaranteed to not invalidate the pointer at any time during
the scope of 'ch'.
> Perl-like hash tables?
In my Python code I use the builtin dictionary type and a unique string
identifier for each object. The id is then stored, rather than references
to another object, and when it's needed we do (pseudo-codish),
cd = character.charDictionary # Alias
class EarlyDetectionSystem(Object):
def tripped(self, tripped): # Setup as ON_ENTER listener.
if cd.has_key(self.owner):
owner = cd[self.owner]
report_to = owner
else:
report_to[:] = everyone[:]
report_to.remove(tripped)
report_to.message( \
tripped.name + " tripped the EDS at " + \
tripped.location.name + "!")
# expire after N uses
self.uses = self.uses - 1
if self.uses < 1:
self.fromloc()
del self
# end tripped
# end EarlyDetectionSystem
Objects and instances have different ids. Basically, we define a factory
function that creates a new object instance. It takes its "prototypes"
unique id and munges it. So if the id was, "eds," the first instance
would be, "eds__instance_0," the second instance, "eds__instance_1," etc.
> I'll see if I can't write a general way using a sort of named lookup
> thing... get_value(chidnum,"gender"); or something..
That will require (potentially excessive) casting.
byte sex = *((int *) get_value(chidnum, "gender"));
and will potentially be slow, depending upon how you implement the lookup
for data elements within the character. At that point, it'd almost be
better to use a complete generic attribute system stored on the character.
The lookup wouldn't be that much more expensive and the flexibility of not
having a type system for your wajas (world whatcha-ma-jiggers; i.e., an
item, room, character, whatever) could be interesting (but allow nothing
that couldn't be faked and be just as playable as far as the player is
concerned).
As an aside, Microsoft's C# (which, surprisingly, they actually submitted
to the ECMA standards board) language provides property get/set methods
that aid in rapid application development (e.g., "code evolution") that
could find interesting applications, here:
public class CharacterId
{
private long _cid;
public string Name {
get { // as in, writeLine (cid.Name);
Character obj = FindPointer (_cid);
if (obj == null)
throw new Exception ("Bad character.");
return obj.Name;
}
set { // as in, cid.Name = "";
Character obj = FindPointer (_cid);
if (obj == null)
throw new Exception ("Bad character.");
obj.Name = value;
}
}
.
.
.
}
In this case, you would treat CharacterId precisely as you would the
Character class. The underlying, invisible property code would handle the
differences in a user-transparent manner. (This is both a good and bad
thing.)
-dak : Please cite your quotations properly. This makes it much easier to
keep track of the thread if you miss a post, etc.
+------------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
| http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
+------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 04/10/01 PDT