12 Mar, 2010, Runter wrote in the 1st comment:
Votes: 0
Okay. Here's my OLC meta programming idea I'm working with right now. Here's what I've got working so far. I need opinions from the perspective of others who would use this or suggestions to stream line it better.

class Room
define_editor :redit
define_editor_commands {:var=>"name", :expected_args=>:arg_str, :filter=>:string_to_string},
{:var=>"sector", :expected_args=>:arg_str, :filter=>:string_to_sector},
{:var=>"exits", :command_name=>"exit add". :expected_args=>:arg_str, :filter=>:string_to_exit, :flags=>additive}

end

class Monster
define_editor :medit
define_editor_commands {:var=>"gold", :expected_args=>[:arg_int, :arg_int], :filter=>:args_to_array}
end



Adding to additional classes shouldn't be too difficult. Obviously I have to add to filter definitions for various things.

This entire thing assumes the editor syntax of "command value1 value2 value3" etc. It doesn't support multiple line interface and decision trees.

Oh, and in most cases the flags are not needed to be set nor the command name field. The command name if it isn't set is the same as the variable name.
12 Mar, 2010, David Haley wrote in the 2nd comment:
Votes: 0
It's not clear how the exits version will work. The others are simple enough in setting stuff, but exits is a collection of exits, not a single variable that you set. OK, there's a flag=additive, but how do you delete an exit? What about when an exit is created for something that already exists? How do you differentiate between variables that can be repeated and those that can't? What about commands that require several arguments? (For example, adding exits in direction to target room.)

I might think about having the command specify a list of token names required, and the command syntax would pass the tokenized input into that list. And then filters would be defined on each token. So, something with multiple variables could be:

args = direction, target
filters = direction=> string_to_direction, target=> string_to_room

This doesn't solve the problem of additive vs. replacing entries, though. Basically the problem is what things are set-based attributes (on which key?) and what things can be specified multiple times. A good example is that a room can presumably only have one 'north' exit but could have several mobs of the same type/vnum/id/whatever.
12 Mar, 2010, Runter wrote in the 3rd comment:
Votes: 0
David Haley said:
It's not clear how the exits version will work. The others are simple enough in setting stuff, but exits is a collection of exits, not a single variable that you set. OK, there's a flag=additive, but how do you delete an exit? What about when an exit is created for something that already exists? How do you differentiate between variables that can be repeated and those that can't? What about commands that require several arguments? (For example, adding exits in direction to target room.)




I didn't include the command to remove the exits but there's an additional flag for that and it works basically the same way.

I should say I've added an additional metafunction called define_abstract_editor_commands…but I'm working so it won't be used. It simply adds a definition to the command table and passes the arg to a function like most OLCs do. Using the define_abstract_editor_commands would force the programmer to write most of the code to make it work. It would be intended for the cases that just aren't caught, or just aren't viable to be caught, or just happen to be easier to do that way.

In any event the syntax would be "exit add <arguments specified by string_to_exit>".

":expected_args=>:arg_str, :filter=>:string_to_exit,"

That tells it to pass the entire string to our filter which converts the string for a specific format to an exit. Any time I have complex (or more complex than very simple data transformation) I have custom filters.

Right now just for testing purposes I'm doing "exit add <direction> <destination>". I'm doing a lot of refactoring as I go and it's changing pretty rapidly from just what I had last night. My goal is getting it as empowered as possible to do all of the coding to add editors/editor commands. Ideally once the entire code is set I can take absolutely any class in the MUD and with 2 simple to read lines of code have an editor set up and live–No reboot required.
12 Mar, 2010, David Haley wrote in the 4th comment:
Votes: 0
Ah, I didn't realize that arg_str meant the entire input line, not just a single tokenized argument.

It's certainly an interesting idea and one that dynamic languages are well-suited for. In principle any attribute can be detected and modified, and this indeed could happen automatically.

There's an interesting distinction to be made between code state attributes and builder state attributes. I would need to think about this more to articulate it, but basically it has to do with separating the various attributes that are for internal representation vs. the attributes of the game entity as far as builders are concerned. (You wouldn't want to present implementation details as OLC-editable attributes.)
12 Mar, 2010, Runter wrote in the 5th comment:
Votes: 0
David Haley said:
Ah, I didn't realize that arg_str meant the entire input line, not just a single tokenized argument.

It's certainly an interesting idea and one that dynamic languages are well-suited for. In principle any attribute can be detected and modified, and this indeed could happen automatically.

There's an interesting distinction to be made between code state attributes and builder state attributes. I would need to think about this more to articulate it, but basically it has to do with separating the various attributes that are for internal representation vs. the attributes of the game entity as far as builders are concerned. (You wouldn't want to present implementation details as OLC-editable attributes.)


Yes. Obviously this would allow the OLC to edit questionable fields. Perhaps things that even can break stuff. On the other hand, though, so does any OLC if a coder who has access to the core is foolish enough to actually enable those fields to be edited. I mean, by default everything is not editable. So with this system a coder would specifically have to specify which fields and what variables can indeed be edited.

It might be fun to play around with the idea of making entire structures available for examination from inside of the game.

One of the problems I'm currently trying to find a solution to is how to add additional OLCs that perhaps have different ways to reference their class instances. For example…if I made an OLC for something like, oh, exits. The way I reference them may be vastly different from the way I reference other things.

One approach I could take is anything accessible in the gamespace automatically becomes a good candidate for OLC. That is to say, if there's *any way* to interact with something generically it would require no extra code to "look it up". If I can look at a monster, poke a monster, etc etc. Then I already have the means to access it generically. The real problem comes when there is no such thing. Then I have to start thinking about specific interfaces to lookup various instances of various classes. I could come up with some uniform policy. The class must implement a uniform way of looking it up. Be it vnums or tags or whatever, but that seems restrictive.
12 Mar, 2010, David Haley wrote in the 6th comment:
Votes: 0
Runter said:
One approach I could take is anything accessible in the gamespace automatically becomes a good candidate for OLC. That is to say, if there's *any way* to interact with something generically it would require no extra code to "look it up". If I can look at a monster, poke a monster, etc etc. Then I already have the means to access it generically. The real problem comes when there is no such thing. Then I have to start thinking about specific interfaces to lookup various instances of various classes. I could come up with some uniform policy. The class must implement a uniform way of looking it up. Be it vnums or tags or whatever, but that seems restrictive.

Yeah, another problem here is the issue of scope: sometimes you might only be referring to things in the same room as you – assuming the MUD has rooms in the first place! – and other times you might be referring to things anywhere in the world, but perhaps with a preference as to what should be matched first…

I've always thought it would be very cool if you could generically define commands like this:

command POKE
syntax target_actor

and then, when the interpreter sees that you used the command 'poke', and it sees 'target_actor, it knows to resolve the input to an actor that can be targeted. More generally, you could specify any kind of argument resolution method. But this gets clumsy when you need to specify things like target_actor_in_room, target_actor_in_world, etc.

Another example might be:

command GIVE
syntax possessed_obj target_actor

which also shows the clumsiness of target_obj vs. possessed_obj vs. worn_obj vs. held_obj vs. …


As you say, you can use something like vnums/ids to look things up, but that's not very convenient (and besides you need to resolve a string to an entity to get its vnum…), let alone feasible for players to use.
12 Mar, 2010, Runter wrote in the 7th comment:
Votes: 0
David Haley said:
I've always thought it would be very cool if you could generically define commands like this:

command POKE
syntax target_actor


Do you mean inside of the game itself?
22 Mar, 2010, Runter wrote in the 8th comment:
Votes: 0
I've somewhat finished this system. Now I'm trying to determine how to display fields and values. My initial thought is generate the display generically. The other idea is possibly letting the display form be defined specifically with some type of markup. Perhaps a combination of the two: Display generically unless the form is defined.

Any input is appreciated.

edit: (as it relates to displaying the values to builders in a menu.)
12 Apr, 2010, David Haley wrote in the 9th comment:
Votes: 0
Oops, it occurred to me that I never answered your request for clarification.

At the moment, I don't really have a statement to make about where one defines these commands. The idea I'm playing with is having some way of writing command prototypes like you would write function prototypes. That is, just as you might write:

void foo(int arg1, char* arg2, CHAR_DATA* arg3);

it might be nice to write:

poke(Actor target)

or:

get(Object thing)

where you could even overload them:

get(Object thing, Object source)

Then, the command interpreter does something similar to what a compiler might do; it looks at your arguments and tries to resolve them against the list of "command prototypes". It then picks the right one based on type matching.

Of course sometimes this is difficult, because the notion of looking up an object can be context-dependent. We've talked about many issues regarding scope and so forth (some commands affect objects in your inventory, others on the ground, others yet objects elsewhere entirely, especially admin commands).

Still, it just seems that so very much boilerplate is needed in every command to do the same old tasks of matching string arguments to targets; surely there must be a way to improve that.

(I don't know if my suggestion here actually works or is even a good idea: I'm just thinking out loud. (But Runter knows that I actually have my reply strategy planned out 20 deep.))
12 Apr, 2010, Runter wrote in the 10th comment:
Votes: 0
Well, since David necro'd this thread I thought I'd share my end result.

>edit
found> [Room room.mike.seven) … Default Value]
__________________________________________________________________________
_ROOM_EDITOR: [ROOM ROOM.MIKE.SEVEN) … DEFAULT VALUE]________________
[vtag]: room.mike.seven
[zone]: [Zone first.area … Default Area Name]
[name]: Default Value
[sector]: sect_city
[flags]: [ ]hidden
==========================================================================
[description]:
There is little unique to be seen here.
—-
[exit east]: [Room room.mike.ait) … Default Value]
[exit west]: [Room room.india.siks) … Default Value]
==========================================================================
[DELETE]: Deletes Entire Room
==========================================================================
[done]
[12:45PM]>

It's MXP enabled and can be navigated through clicking on the various links it produces. Like clicking on the exit to enter the exit editor, or clicking the room to begin editing a connecting room, etc.

The entire view and control component is generated from the metaprogramming mentioned earlier such as:
class Room
define_editor :room_editor
define_editor_field({:name=>"vtag", :filter=>:filt_to_tag, :type=>:vtag})
define_editor_field({:name=>"zone", :filter=>:filt_to_area, :type=>:namespace})
define_editor_field({:name=>"name", :filter=>:filt_none})
define_editor_field({:name=>"sector", :filter=>:filt_to_sect})
define_editor_field({:name=>"flags", :filter=>:filt_to_flag, :filter_key=>$room_flags, :type=>:flags})
# <snip>
end
12 Apr, 2010, flumpy wrote in the 11th comment:
Votes: 0
Looks good :) Liking it.
0.0/11