On 9/10/2010 10:58 AM, Ralph Versteegen wrote:
On 10 September 2010 03:18, James Paige<[email protected]> wrote:On Thu, Sep 09, 2010 at 10:18:41PM +1200, Ralph Versteegen wrote:Well, this email was originally going to be part of the one about SAV, but then I remembered that NPC instance data has never been read from .SAV!I'd like start adding of data to NPC instances, like zone restrictions. (I'll have to create an NPC instance editor.) Actually, I already started. A few months ago I wrote these (below), but didn't check them in because I was waiting for .SAV to be dropped. Opps! Sorry Jeremy! But anyway, I just thought I may as well ask about functions for reading/writing NPC instance data. functions: 472,setnpcbit,3,0,0,1 #set NPC instance bit (npcref, bit, value) 473,getnpcbit,2,0,0 #get NPC instance bit (npcref, bit) constants: 0,NPCbit:ignore walls 1,NPCbit:not obstruction 2,NPCbit:suspend use 3,NPCbit:suspend movement (Incidentally, those "bits" are not actually stored as bits in the UDT.) And then other non-flag data like zone restrictions would each get a pair of getter/setting functions. Would people prefer something more uniform like alter/read npc (below)? Or the opposite extreme of individual read/write functions for each bit? 472,read npc instance,3,0,0,1 #set NPC instance data (npcref, data id, value) 473,write npc instance,2,0,0 #get NPC instance data (npcref, data id) 0,NPCinst:ignore walls 1,NPCinst:not obstruction 2,NPCinst:suspend use 3,NPCinst:suspend movement 4,NPCinst:zoneI like individual functions for each bit. I may have advocated generic functions with constants in the past, but I am really starting to hate the heck out of them. it is all about what I want to be writing as an end-user in my script: # this is good set npc ignore walls(npc, true) # this is bad set npc bit(npc, NPCbit:ignore walls, true)Well, I choose the second approach because I hate having too many functions (and having to document them :) ), because it makes the dictionary extremely verbose: consulting a compact table as for alternpc is much faster (I actually prefer read/alternpc to trying to remember over 100 menu functions, for example). And our commands are inconsistent and difficult to remember as a rule -- I can never remember whether to use "slice parent" or "parent slice" -- so I end up looking up an awful lot. However a few paragraphs of documentation for every tiny bit is much more fair for people who aren't familiar with engine internals in the first place. However despite all that, I must agree with you: I didn't realise how overly verbose the setnpcbit approach was. But while we're on the topic of too many functions which are impossible to remember, I think I'll sidetrack into adding structures to HS, which I've been meaning to talk about. Having actually used Euphoria a whole a couple months back, I take back what I said about it being a nice language. I think not supporting user defined data structures in the new HamsterSpeak is out of the question, it's just unworkable. And following this train of reasoning, if we have user defined structures, and function objects, then we may as well add some form of object orientation, since you're already nearly there. And if we now present a slice handle, npc reference, menu handle or whatever else as an object with members and/or methods, we can provide an alternative way to interact these objects that's less verbose, highly consistent, easy to remember and compactly documentable: menuitem.caption instead of get menu item caption (menuitem) heroes[who].stats[stat.hp] += x instead of set hero stat(who, stat:hp, get hero stat(who, stat:hp) + x) and so on. The exact details don't matter right now, but this is very similar to the Magic Variables plan.
I'm having deja vu; this is a lot like the transition between the mathematical operators being functions and them being actual symbols. (although, this transition occurred long before I had ever used the OHR)
Hypothetically speaking, how would you implement these structs? Would you go for a classical model (like how they work in C), or something else?
If you're looking for suggestions, I think Lua has the best system. Basically, every variable that isn't a basic type (integer, string, etc) is a table (i.e., a set of key->value pairs). If the indicies are numeric, you call it an array, whereas if the keys are strings, you call it a hash. If the values are functions, then it must be an object.
Even better, you can set what's called a "metatable", which defines functions that are called when the table is operated on, which allows you to simulate properties. The identity of an object is based on its metatable. If get_metatable(objA) == get_metatable(objB), then they must be instances of the same class.
One of Lua's interesting quirks is that it actually has two ways to invoke methods on objects. If you use the dot operator (myobj.method()), it's called normally (eg, just as method()). But, if you use the colon operator (myobj.method()), it's called by passing the table as the first operator (eg, method(myobj)).
As I said, I know the library is already full of stuff that does it the second way, I just wish now that it wasn't. But I suppose this is a matter of personal taste, and my opinion on this is certainly not the final word. --- James _______________________________________________ Ohrrpgce mailing list [email protected] http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org_______________________________________________ Ohrrpgce mailing list [email protected] http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org
_______________________________________________ Ohrrpgce mailing list [email protected] http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org
