18 Mar, 2010, Runter wrote in the 1st comment:
Votes: 0
So right now my commands are objects. Players have collections of these objects.


Command.new("look",     [[:arg_int!], [:arg_none]])
Command.new("east", :arg_none)


So I'm trying to bake 100% of the type checking into the dispatcher for the commands. Hopefully to save work when adding commands since you can be guaranteed the types passed are valid and already converted. This starts to get more complex as you have multiple types for a single argument that can be passed. So focusing on just the second argument (the 2d array):

[[:arg_int!], [:arg_none]]


Each list in the list represents a valid argument chain. So in this case it knows it can cast the arg to int or it can pass no value. Nothing else is valid. It can hold any number of values. For example:
[[:arg_int!, :arg_int!, :arg_word!],
[:arg_obj_in_room],
[:arg_str]]

This would tell it that the command has 3 possible arg chains. The first being int, int, word (in that order), the second being an object found in the same room as player, and the third being any string not empty that doesn't match the first two. In the case of the obj_in_room and similar non-primative types it will do the magic to find the object before passing the arg. If the object isn't found then it considers that a fail just as though the passed argument was invalid.

I'm curious if anyone else has tackled this problem and what they learned at the end of the day. Right now it's seeming manageable but I'm worried about it getting any more complex in syntax than that for building the arg-option-trees. Any opinions on the matter would be helpful.
18 Mar, 2010, kiasyn wrote in the 2nd comment:
Votes: 0
Have you looked at the way rails does routes?
18 Mar, 2010, Deimos wrote in the 3rd comment:
Votes: 0
Well, it seems like you're trying to use the system for more than just type checking (ex. :arg_obj_in_room). If this is the case, I wouldn't try to incorporate everything into one symbol or I can see how it could get too complex. Maybe instead of :arg_obj_in_room, you could say :arg_type_obj and :arg_location_room. This allows you to build very complex restrictions later with a relatively small number of building blocks. For example :arg_type_obj, :arg_material_silver, :arg_alignment_good, :arg_location_room, instead of :arg_obj_made_of_silver_has_good_alignment_in_room.

Anyway, I think it's a cool idea you've got.
18 Mar, 2010, Runter wrote in the 4th comment:
Votes: 0
Deimos said:
Well, it seems like you're trying to use the system for more than just type checking (ex. :arg_obj_in_room). If this is the case, I wouldn't try to incorporate everything into one symbol or I can see how it could get too complex. Maybe instead of :arg_obj_in_room, you could say :arg_type_obj and :arg_location_room. This allows you to build very complex restrictions later with a relatively small number of building blocks. For example :arg_type_obj, :arg_material_silver, :arg_alignment_good, :arg_location_room, instead of :arg_obj_made_of_silver_has_good_alignment_in_room.

Anyway, I think it's a cool idea you've got.


Hrm. You may have a point, but it's going to get complex fast if I add another dimension to that array for building filters too. Maybe I can have an area for constructing filters separate so it doesn't get confusing. In any event, I'll explore this idea and see how it turns out. Thanks for the input.
18 Mar, 2010, David Haley wrote in the 5th comment:
Votes: 0
I think we were talking about that problem in the OLC Metaprogramming thread as well. It gets silly pretty quick to need a cross-product of all attributes you want to test on. Even without testing materials and so forth, there are enough options with objects being held, carried, worn, in the room, on other people in the room, in the world, etc., that you would quickly need a flexible way to handle all this.
18 Mar, 2010, Runter wrote in the 6th comment:
Votes: 0
David Haley said:
I think we were talking about that problem in the OLC Metaprogramming thread as well. It gets silly pretty quick to need a cross-product of all attributes you want to test on. Even without testing materials and so forth, there are enough options with objects being held, carried, worn, in the room, on other people in the room, in the world, etc., that you would quickly need a flexible way to handle all this.


Well, I was considering just doing very general conversions. Like being able to guarentee at the command level that the object is the one the player selected that was in the room with them. It would then be up the the function to determine if it's an operation that can be taken on the object. For example the get command. I don't think I'd want to have the filters determine if they're too heavy, etc. Instead, I just want to ensure it was selected by the parser before the command is issued. So I probably wouldn't go beyond the options you listed.

However, I wonder if it would be easier to construct ways tags can work together in complex ways or just manually define the filters I would need. Just seems to me if I stay with a limited scope for the system defining all of the various tags it would be more work than just defining the filters.
18 Mar, 2010, Deimos wrote in the 7th comment:
Votes: 0
Well, if that's the case, I would just constrain it to type-checking only. In the case of :arg_obj_in_room, you're mixing type-checking (obj) and error-checking (in room). If you do all your type-checking at the dispatcher level, and leave the error checking up to the commands, the system is more departmentalized, IMO. Having some error-checking here and some there doesn't sit well with me for some reason, but I'm sure it would work just fine either way. I can certainly see the benefits to pulling out some of the more common error checks (like in_room), since that's a lot of repeated code, but you'll likely run into the "where do I stop" issue when trying to decide what should be pulled out or left in.

Just my $0.02.
18 Mar, 2010, Runter wrote in the 8th comment:
Votes: 0
Deimos said:
Well, if that's the case, I would just constrain it to type-checking only. In the case of :arg_obj_in_room, you're mixing type-checking (obj) and error-checking (in room). If you do all your type-checking at the dispatcher level, and leave the error checking up to the commands, the system is more departmentalized, IMO. Having some error-checking here and some there doesn't sit well with me for some reason, but I'm sure it would work just fine either way. I can certainly see the benefits to pulling out some of the more common error checks (like in_room), since that's a lot of repeated code, but you'll likely run into the "where do I stop" issue when trying to decide what should be pulled out or left in.

Just my $0.02.


Yeah, but I don't have any preconceived notion of what pattern I should be following for pattern's sake. I'm just developing based on what I think will be best for development in the future. Many spellcasting parsers in different codebases use this type of type-logic checking and it seems to work.
18 Mar, 2010, David Haley wrote in the 9th comment:
Votes: 0
I don't know how you could do reasonable type checking without knowing the location (or more generally, 'scope'). If the syntax is "get <obj>", and you type "get sword", how is it possibly going to know which sword you meant to take? Basically the scope constraint is important because it lets it know which objects to be comparing your string against.

I agree that there is some question of where one stops, but I think that the common scope cases should be very easy to express.
18 Mar, 2010, Runter wrote in the 10th comment:
Votes: 0
Well, right, and I don't see that many scopes required. If something is unique enough to require a more precise scope it's granularity can be adjusted after it's passed to a function. And I can mitigate some of the issues with accidentally selecting one you naturally thought were out of the scope simply by handing off a queue of objects that were selected.

So if I'm looking for obj_in_inventory and our command is "throw s" then we'd expect the first object selected by the parser to be passed to the command function. If I have the parser not stop at the first but collect in order of relevance all items that match the description within the scope of inventory our list might look like:
a signet ring, a silver bar, a short sword

It's easy enough for the command function to select from the array parameter the first object with the property of being a throw-able weapon. As far as the player is concerned, the command parser never used ring or bar for consideration. This makes it slightly a better outcome than the player having to type "throw 3.s" or something similar.

edit: of course if you don't mind forcing players to be very specific even when the parser should have been a little smarter it may be accepted for some people to require "throw short sword"

found = arg_passed.select {|obj| obj.type == :type_weapon}


Something like that anyways. :p
18 Mar, 2010, Deimos wrote in the 11th comment:
Votes: 0
David Haley said:
I don't know how you could do reasonable type checking without knowing the location (or more generally, 'scope'). If the syntax is "get <obj>", and you type "get sword", how is it possibly going to know which sword you meant to take? Basically the scope constraint is important because it lets it know which objects to be comparing your string against.

Well, the way I would do it is to give each command a scope precedence chain, and it would then just match the first object it finds in the chain. You need this anyway to handle situations involving multiple scopes, like "get <obj> <container>", so I would just add it as a property of the command, rather than putting it in each command's logic (or the dispatcher's).

Command.new( "get", [ :scope_room, :scope_inv, :scope_equipped ], [ :arg_obj, [ :arg_obj, :arg_obj ] ] )
18 Mar, 2010, jurdendurden wrote in the 12th comment:
Votes: 0
Deimos your new avatar is freaky. :P
18 Mar, 2010, Tyche wrote in the 13th comment:
Votes: 0
jurdendurden said:
Deimos your new avatar is freaky. :P


It's disturbing…I want to grab a shovel and kill it.
18 Mar, 2010, Tyche wrote in the 14th comment:
Votes: 0
Deimos said:
Well, the way I would do it is to give each command a scope precedence chain, and it would then just match the first object it finds in the chain. You need this anyway to handle situations involving multiple scopes, like "get <obj> <container>", so I would just add it as a property of the command, rather than putting it in each command's logic (or the dispatcher's).

Command.new( "get", [ :scope_room, :scope_inv, :scope_equipped ], [ :arg_obj, [ :arg_obj, :arg_obj ] ] )


Consider attaching an environment (scope) on the player object.
And where is security of commands handled Runter?
18 Mar, 2010, Deimos wrote in the 15th comment:
Votes: 0
Tyche said:
Consider attaching an environment (scope) on the player object.

Not sure what you mean by "attaching an environment on the player" - are you suggesting a :scope_player in place of :scope_inv and :scope_equipped?

jurdendurden said:
Deimos your new avatar is freaky. :P

Tyche said:
It's disturbing…I want to grab a shovel and kill it.

Haha. Glad you like it.
18 Mar, 2010, Runter wrote in the 16th comment:
Votes: 0
Tyche said:
And where is security of commands handled Runter?


Right now they're separated into tables that at as permission groups. Currently only have global_commands, olc_commands, and staff_commands. Each player has their own group that can contain duplicates too, if they have been granted commands from places that aren't naturally available to them as well as environmental commands that aren't available to perhaps everyone.
18 Mar, 2010, Runter wrote in the 17th comment:
Votes: 0
Deimos said:
David Haley said:
I don't know how you could do reasonable type checking without knowing the location (or more generally, 'scope'). If the syntax is "get <obj>", and you type "get sword", how is it possibly going to know which sword you meant to take? Basically the scope constraint is important because it lets it know which objects to be comparing your string against.

Well, the way I would do it is to give each command a scope precedence chain, and it would then just match the first object it finds in the chain. You need this anyway to handle situations involving multiple scopes, like "get <obj> <container>", so I would just add it as a property of the command, rather than putting it in each command's logic (or the dispatcher's).

Command.new( "get", [ :scope_room, :scope_inv, :scope_equipped ], [ :arg_obj, [ :arg_obj, :arg_obj ] ] )


How do the values in the first array correspond to the values in the second array? I think I'm not following.

Edit: I think I see what you mean, but I think the notation would have to be different. It's possible the type of args are different and the scopes wouldn't apply or wouldn't make sense if you globally applied them. Also, "get sword" shouldn't let me get items that are in :scope_equipped.
18 Mar, 2010, Deimos wrote in the 18th comment:
Votes: 0
Runter said:
How do the values in the first array correspond to the values in the second array? I think I'm not following.

Edit: I think I see what you mean, but I think the notation would have to be different. It's possible the type of args are different and the scopes wouldn't apply or wouldn't make sense if you globally applied them. Also, "get sword" shouldn't let me get items that are in :scope_equipped.

Well, yeah. It depends on how your system is set up. Try as I might, I couldn't think of a command where argument types would change based on number of arguments. That's dependent on your particular command structure, though. The two arrays are independent in my example. You would handle any error checking, like your "get sword" example, inside the command logic (where I think errors should be handled). I guess you could change the notation so that you had a scope precedence chain attached to each argument list if you wanted to handle those errors in the dispatcher, though.
18 Mar, 2010, Tyche wrote in the 19th comment:
Votes: 0
Deimos said:
Tyche said:
Consider attaching an environment (scope) on the player object.

Not sure what you mean by "attaching an environment on the player" - are you suggesting a :scope_player in place of :scope_inv and :scope_equipped?


Well, I'm presuming the Command must be executed in context of the Player/User/critter somewhere… somehow. Instead of passing a bunch of scope variables, the player/user object might have the "environment/scope list" associated with it. That way a user can configure the scope themselves beyond the system default.

Also consider allowing the entire command interface to be user configurabe, then "get" isn't literally "get", but a perhaps a symbolic function :get which could be associated with "take", "get", "pick up", whatever.
18 Mar, 2010, Runter wrote in the 20th comment:
Votes: 0
Deimos said:
Runter said:
How do the values in the first array correspond to the values in the second array? I think I'm not following.

Edit: I think I see what you mean, but I think the notation would have to be different. It's possible the type of args are different and the scopes wouldn't apply or wouldn't make sense if you globally applied them. Also, "get sword" shouldn't let me get items that are in :scope_equipped.

Well, yeah. It depends on how your system is set up. Try as I might, I couldn't think of a command where argument types would change based on number of arguments. That's dependent on your particular command structure, though. The two arrays are independent in my example. You would handle any error checking, like your "get sword" example, inside the command logic (where I think errors should be handled). I guess you could change the notation so that you had a scope precedence chain attached to each argument list if you wanted to handle those errors in the dispatcher, though.


It defeats the whole purpose if I can't be guarenteed something dispatched was a candidate. I.e., it picking the shirt I have worn instead of the shirt on the ground when typing "get shirt" and returning "Can't get something you're wearing." From my proposed example with select I was already getting better results than this since as far as the player is concerned when they type "get shirt" it grabs the shirt on the ground.
0.0/39