03 Oct, 2008, Silenus wrote in the 1st comment:
Votes: 0
I come primarily from an LPC background where the in game language is rather general purpose. Unlike most Very High Level languages it supports type annotations though the rules for checking these are probably not always clear to newcomers and occasionally differed to runtime or simply ignored. The question I have is whether any one has developed good Turing complete languages for doing specifically mud interaction scripting- that is used specifically to specify AI actor's action and responses… event scripts where you have a scene which needs to be played out before the player with multiple participants and props etc and so on.

I noticed most mudlibs in LPC completely lack such a sublanguage- perhaps because of the power of LPC the smaller semantic gap and convenience is offset by the general complexity of implementing a sublanguage or library given LPC's design. But outside the LPC world I wonder if such things are reasonably common. Are they?

Thanks in advance,

03 Oct, 2008, David Haley wrote in the 2nd comment:
Votes: 0
What kind of thing are you talking about specifically? Do you have an example of what you would want to script with this?
04 Oct, 2008, Silenus wrote in the 3rd comment:
Votes: 0
Consider for example an innkeeper which responds to player requests perhaps in a stateful manner depending on the time of day and his/her mood and which might perform a series of actions depending on the circumstances of a request made by a player. For example the player might say "xxx, I would like to buy a meal."- the innkeep would proceed would respond with a series of actions 1. acknowledge the players request and take the money. 2. head to the kitchen to speak to the chef. 3. make a request of the chef. 4. then return and inform the player if he hasn't left the room that the meal is being prepared. 5. If the player is not to be seen queue in his memory that the player perhaps needs to be informed. 6. Return to his previous position in case other players have additional requests. Obviously all this should be done with relevant time delays in between.

Another example might be an encounter or boss encounter scene which has a prologue prior to the encounter and an epilogue depending on the outcome of the encounter. Multiple actors maybe involved in dialogue and actions with appropriate time delays and depending on a players actions the "dialogue" may take different courses leading to different results. Again with appropriate time delays.
04 Oct, 2008, David Haley wrote in the 4th comment:
Votes: 0
Hmm ok. Why do you feel the need for a DSL, and not just whatever normal scripting language? (Luaish, Pythonish, Rubyish, etc.)
04 Oct, 2008, Silenus wrote in the 5th comment:
Votes: 0
Well my thoughts are that it would be easier to handle in a scripting system of some sort rather than in the general purpose language might have some savings. I am just wondering if a simpler interface (scripting language) can be provided for beginners i.e. in LPC the way to do something like this might be-

object innkeeper = find_object(xxx);
object sil = find_player("silenus");

if( some condition ) innkeeper->eventForce("say hi");

// wait for player action.

if( some condition ) { innkeeper->processBuy(player, item); innkeeper->eventForce("Thank you $N here is your $O", player, item); }

This quickly can get quite messy because of the entry points into the system, the fact that it's state based plus the callback structure. I am wondering if there are simpler solutions rather than forcing ppl to write alot of this sort of code or if naturally this sort of thing would have to be done anyhow which means in general most coders wont do much AI scripting since it's far more complex than sticking a plain monster in a room.
05 Oct, 2008, exeter wrote in the 6th comment:
Votes: 0
The reason (IMO) that most LPC MUDs don't have any such language is that the mudlib itself acts as a domain-specific language for describing interactions among game objects.
05 Oct, 2008, David Haley wrote in the 7th comment:
Votes: 0
Silenus said:
the fact that it's state based

How could something like this not be state based?

You mentioned that you wanted the language to be "Turing complete" – I'll assume that what you really mean is "sufficiently complex to do interesting things" (without getting into theory of computation etc.). With that in mind, isn't it almost necessary for the language to be non-trivial syntactically?

What I would suggest is coming up with a mock-up of sorts that demonstrates the simplicity of scripting the innkeeper exchange, while allowing you do to interesting things. And then compare with a "smart" implementation in LPC (or whatever), showing that you are doing things more simply than is possible in LPC. It's possible that the "DSL" could just be whatever language you're already using, but with lots of helper functions that make life easier for the writer: common patterns or constructs can be encapsulated into library functions or objects.

(EDIT: s/patters/patterns/, oops)
05 Oct, 2008, Vassi wrote in the 8th comment:
Votes: 0
Silenus said:
Well my thoughts are that it would be easier to handle in a scripting system of some sort rather than in the general purpose language might have some savings. I am just wondering if a simpler interface (scripting language) can be provided for beginners

Savings for who? You can still provide a simple interface for beginners by exposing a specific, and coherent, object model to a "general purpose" language. For instance, I'm using IronPython (which is basically Python that talks .NET) which works fine on its own but is much more useful once I start exposing objects to it. One of the things every one of my exposed objects has is a small class I built in five minutes called ScriptTags to handle state. Basically you log a tag with a key (that will hopefully be script\quest specific via a naming scheme) you fill the tag with an int and\or a string, and you set an expiration time stamp. The timestamp is checked when you request it, if the tag you're requesting exists - but has expired - it is deleted and you are told it doesn't exist.

Anyway, building a meaningful and easy to learn object model to an existing language is easier than finding a whole new, tailored, language to do exactly what you want. At that point all your 'beginners' have to do is learn the syntax basics of the language you're using, as well as basic conditionals and looping, and they're good to go.

Edit: Woops, didn't mean to repeat what David said, so in short: I agree.
05 Oct, 2008, Silenus wrote in the 9th comment:
Votes: 0
Actually I am well aware of some of the issues involved- i.e. you trade away in most languages your existing syntax for a foreign syntax which requires an effort to learn. I actually have already done such an exercise but ran out of good ideas on how to structure such code which would provide real savings in terms of code complexity. I am also not above using language extensions via libraries to get the job done.

By state based I meant in contrast to most interactions with npc objects which are effectively stateless even if they have some sort of rudimentary "AI". I believe certain libraries in LPC have a not so Turing complete language for simplifying some aspects of mud scripting though not the aspect that I am particularly interested in- i.e. Lima contains a Lpscript which seems to be there for simplifying the configuration of mud objects.

The callback structure of LPC makes alot of this quite complex if done naively. If you wrap the code in a library which allows for function pointer hooks. How this too is still problematic due to implementation issues in the language if you use anonymous functions and retain textual locality the runtime errors coming out of the system do not report back properly.

The reason I asked the initial question was I was wondering if there are better approaches out there to this problem than my simple mock-ups and how any such language addresses certain issues with respect to rechecking conditions after possible changes of the state between time delays. My initial sketch of this both library wise and DSL wise was to use guard clauses + command scripts and embedded LPC statements. The issue for me in this in order to keep thing simple is how to and when to recheck modified guard clauses (modified by the command actions themselves) and propagate this modified guard check after a time-delay. The complexity of this becomes however a bit high implementationally. Since the system would have to be able to infer the outcomes of various commands passed in.
06 Oct, 2008, David Haley wrote in the 10th comment:
Votes: 0
Why can't you have the relevant scripts be listeners on the data in question, and whenever it changes it fires a change event? They could then reevaluate the clauses in question, and take whatever action is necessary based on the condition changes, if any.
06 Oct, 2008, Silenus wrote in the 11th comment:
Votes: 0
There are benefits to using an event driven type approach but in this case the script itself may mutate the data causing the guard to become invalid on a subsequent rentry into the script. You could argue that this means that the script should be separated out into a separate listener however this (including the FSA like guard clauses) breaks up the narative structure alot making it hard to follow the flow at a glance.

I am envisioning these scripts as just being a series of commands issued by the actor in question and wondering if the guards can be updated in some manner as the actions occur since you should know in some sense what their pre-conditions and post-conditions are. Nested guards is another possibility- I guess this is an issue similar to type inference though perhaps a bit more complex. I.e. it may be possible in theory to infer in many cases what the condition should be after some action in the script occurs and modify the guard so that upon rentry the new condition conforms to the current state of affairs.
06 Oct, 2008, David Haley wrote in the 12th comment:
Votes: 0
I have to admit that I'm a little confused here. You want the language to be sufficiently complex, yet you talk about it as only a sequence of actor commands in a narration. It would really help me to see an example of how you would script the innkeeper exchange so that I can reconcile the desired complexity with the simplicity.
07 Oct, 2008, Silenus wrote in the 13th comment:
Votes: 0
Well I was initially thinking of a language or interface that looked something like this (Ignore the absence of arguments passed in during event triggers)

block :- guard-clause statement*

guard-clause :- event* conditional-expression

statement :- command delay? | lambda-closure delay? | conditional-expression statement*

command :- actor-name? string // the actual command string

So perhaps

[encounter-player, ((not in-combat? innkeeper)) ]
"Greetings $N! Welcome to our humble inn."
"Can I be of some service?"

[buy-request, ((not-in-combat? innkeeper)) ]
[(not (in-stock? $O))] "I apologize but we have run out of $O!"
["int-stock? $O]
"Please wait a moment let me contact the chef"
"!Go north" 1
"!Ask George to prepare $O" //assumes George is always present for simplicity
"!Go south" 1
"Thanks for waiting $N. George tells me that the food will be ready in 10 minutes." // A server or waiter will subsequently deliver the food

With the escape hatch via lambda closures I think that "the language" is reasonably powerful. The problem is to what extent you can remove some of the explicit condition guards in an environment where the players can perform actions during time delays which can invalidate some of your conditions. What happens for example if the innkeeper gets attacked on the way to the kitchen? Obviously you can make these explicit- but ideally like with type-inference based on some post-condition/pre-condition/invariant logic for commands and re-evaluation of enclosing guards etc might make it possible to remove some of the uglier guards?
07 Oct, 2008, David Haley wrote in the 14th comment:
Votes: 0
You could treat it as a sequence of tasks as opposed to actual commands. The task of asking for the food to be prepared is conditioned on the innkeeper not being in combat. The task is broken into three sub-tasks: (1) going to the room, (2) making the request, (3) returning to the storefront. Task 2 depends on task 1 being complete. Tasks (1) and (3) are dynamically broken into sub-tasks depending on where the innkeeper is located. If a task is interrupted, you know where you are in the list of accomplished goals.

In other words, don't script a list of actions, script a list of goals with preconditions. Then have a planner engine to work out the details for you based on current conditions. I'm not sure how to best represent this syntactically but I imagine it wouldn't be too bad.
07 Oct, 2008, effigies wrote in the 15th comment:
Votes: 0
I think you need to recheck your LPC foo. 1) Lima is old, unsupported, and was really weird when it was supported. 2) scripting NPCs to do different things based on conditions that are represented in game is really trivial in LP. I have most experience with the Nightmare/Foundation/Dead Souls (which is actively maintained and has an active developer community) family, and I know you can build this kind of functionality into a single NPC or into an inheritable so you repeat work as little as possible. 3) Designing an intelligent inheritable is a bit more work in the short run, but easily doable and if you need even more power, you can build some kind of Innkeeper AI daemon that will handle this globally. 4) adding another layer of complexity seems like a bad fit for this to me. If that is what you want to do, then by all means go ahead, but do note that the tools provided can solve this problem even if you don't get how at this point.
07 Oct, 2008, David Haley wrote in the 16th comment:
Votes: 0
There's no need to be hostile about this… it's just brainstorming and thinking about things.
effigies said:
scripting NPCs to do different things based on conditions that are represented in game is really trivial in LP.

I don't think you quite understood what he was trying to do. It's not as simple as saying "if this, do x,y,z". He wants a larger scene to be scripted under a given condition, and that condition must remain true for the duration of the scene. The question is what should be done if the condition is violated halfway through the scene.
08 Oct, 2008, Silenus wrote in the 17th comment:
Votes: 0
You might be correct David that I am taking the wrong approach to the problem and a planning agent of some sort might be a better approach. Unfortunately I do not know much about this approach. The cons here might be that it might be difficult for a person with limited coding experience to quickly decompose a problem into the relevant subtasks effectively- though perhaps a set of properly designed modules might be able to handle this but I am not sure. It might have a range of benefits as well though since you get truly intellgent planning agents capable of a wide range of tasks.

It may be that given how much branching factor there is in scenes with exceptions to the main flow in general that this problem is not solvable in a clean way. You may be able to guard against errors occurring in the main scene narrative by re-evaluating a modified version of the guard condition prior to each delayed action- in the simplest case the guard condition would be unchanged throughout the scene and just re-evaluated (and if something bad occurs throw an exception)- my more elaborate proposal might be that if some action alters the environment/state in some manner which violates the guard- since the action itself is known apriori in most cases would it not be perhaps possible to use some sort of post-condition to modify the guard? I am not sure to what extent such sophistication is needed though- I can think of certain cases such as a guard like "if some object is present" and the first action is get it (changes the environment state and re-evaluation of the guard clause would become inappropriate for subsequent actions).

Effigies- I know you could code a custom inheritable for this for specific cases but I am thinking in terms of a more general scripting mechanism (which could be an inheritable since as I mentioned earlier in the thread it could be a library) which can cope easily with a wide range of diverse situations allowing NPC's to have more dynamic behavior in general rather than having a predefined module with specific behaviors which something like say an innkeeper daemon would imply.
08 Oct, 2008, David Haley wrote in the 18th comment:
Votes: 0
You would have to use fairly high-level constructs to make it easy for non-technical people to give planning directives. Fortunately, that might not be as hard as it looks. In the innkeeper scenario, you could say it like this:

1. Go to room X.
when complete:
2. Order the bread.
when complete:
3. Go to room Y.

You could replace "when complete" with whatever syntax you want, but except for the details of step 2, in the above five lines you have basically captured the entire high-level scene. The planner can figure out how to flesh out steps 1 and 3 pretty easily. The above doesn't capture the initial precondition or trigger, but I think the general idea is clear.

Basically, if you provide the high-level constructs and a simple syntax for specifying dependency chains, it's pretty easy to create simple scenes.

I would tend to agree that, for sufficiently complex scenes (where complexity has to do with branching), there might not be a clean solution, if cleanliness means simplicity of specification.

Simple planning agents are not that hard to write up. It depends on the richness of the environment in terms of what actions are available to the actors and how many consequences those actions can have, and furthermore to what extent the actors understand the consequences. If the goals are fairly simple, and the steps involved are pretty obvious, and finally you can limit the relevant universe to a small subset of the whole MUD world, planning becomes rather cheap. Unfortunately, IMO, it's pretty hard to search for planning code on the web since you tend to get academic work that is usually far more advanced than you (usually) need. You also tend to not find much introductory material.

If you have access to the book AI: A Modern Approach I would highly recommend it as a good introductory textbook to these issues. While it's not all about planning, they have quite a bit devoted to planning agents and how you could go about designing such systems. The book is not about implementation, though, and tends to stay at a fairly high level. I imagine that there are game programming books that discuss planning in more detail but I am not familiar with any.
10 Oct, 2008, Silenus wrote in the 19th comment:
Votes: 0
Thanks. I will take a look at that. I am actually familiar with that title but only skimmed through some of the sections. When I was looking through it I was primarily interested in AI for board games and didnt really look at the chapter on planning. Do most of the techniques require some sort of theorem proving engine to actually process the results? I have been somewhat interested in resolution theorem proving and I guess it's an interesting issue if such a device could be used in certain mud applications specifically stuff like planning and natural language processing for command handling.

I guess any such "mud" would not really be very mud-like by current standards but could be quite interesting. I was thinking of making this a sub-system (a simple TP device) of my server project originally (getting off topic here I know).
13 Oct, 2008, David Haley wrote in the 20th comment:
Votes: 0
I've written and worked with planning systems both with and without theorem provers. Resolution theorem proving is actually pretty simple for the kinds of things you're likely to need. I've used resolution theorem proving in games before, for whatever that's worth. Actually I taught a class twice on resolution, and then once a class where it was applied to game playing… it's definitely workable, but it's easier when you impose constraints on the language in question to make it more tractable. More details if you want them…

Silenus said:
I guess any such "mud" would not really be very mud-like by current standards but could be quite interesting.

What, does having advanced features preclude one from being considered a MUD? :wink: