19 Aug, 2009, JohnnyStarr wrote in the 1st comment:
Votes: 0
Ok, with all this Lua talk, I am hoping someone could suggest a quick example of it
embedded into a mud. I know that Nick Gammon has a thread about it on his site, but
it is for SMAUG, and from previous discussions on this forum, he has chosen his own way
of doing it. Personally, I have a few ideas of my own, but am wondering what anyone out there
would do with it. I have read up on the topic on several sites, and it dosn't seem too difficult (in theory)
but if anyone could present an actual code example of the simplest step, that might help in figuring
out if where to take it next. :biggrin:
19 Aug, 2009, tphegley wrote in the 2nd comment:
Votes: 0
Well, what nick has done with it is quite neat in that you can have quests and area resets using Lua. What exactly do you want to use it with?

What exactly is your question? Do you intend to write your own lua code to input into a mud and asking how to do that or are you looking for how to use Nick's lua example?
20 Aug, 2009, JohnnyStarr wrote in the 3rd comment:
Votes: 0
My intention is to play with it as i go. I want to use it the way Aardwolf does, as a replacement to MobProgs.
And if I find any other uses like quests or resets than I'll probably review nicks example. My issue with Nick's example
is that his walkthrough is hard to translate to ROM (for me anyway), also it does not explain in detail what each Lua -> C and C -> Lua is doing. He includes a src file with a ton of code, but I was hoping someone might suggest a practical way to embed the Lua interpreter into a ROM project. If not, I can hit the books :cool:
20 Aug, 2009, David Haley wrote in the 4th comment:
Votes: 0
I can't suggest a practical way to embed Lua into ROM specifically as I am not aware of ROM's internals. Nick's examples are good for embedding into SMAUG although his approach has some issues if you want to do certain things, in my opinion.

My code creates a userdatum wrapper for each object I want to "reveal" in Lua. The C++ object associates a Lua reference to that object. When the C++ object is destroyed, that reference is released, letting Lua garbage collect its version of the object (assuming nobody else is referring to it). A Lua reference to an invalid C++ object is detected when dereferenced, to avoid crashes (but a Lua error is still generated, which can be caught from within Lua).

Each exposed class is given a metatable with various methods, and each "revealed" object's userdatum is given the appropriate metatable.

A lot of this assumes familiarity with Lua's metatable model; you need to understand metatables before understanding how to embed structures (in C or C++) in Lua.

At some point I will write more about all of this and maybe even give some kind of sample code.
22 Aug, 2009, JohnnyStarr wrote in the 5th comment:
Votes: 0
Ok, well I'm not going to pretend that I fully understood all of that, but it sounds very interesting. :stare:
I do think it would be very helpful for you to post some examples. In the meantime, I'm going to try
to understand more about Lua, and hopefully by then I can make some sense of how that might workout. :cool:
23 Aug, 2009, David Haley wrote in the 6th comment:
Votes: 0
The first thing to understand is metatables in general (they define, among other things, what to do when a field doesn't exist in a table, or how to get fields from userdata), and then understand what userdata are, and finally how one can make a userdatum appear to have fields by using metatables.

It's not easy to given an example for an entire working MUD because there's an awful lot of stuff involved and the example quickly becomes overwhelming. You might want to take a look at item 21 of the Lua Programming Gems; if you want the full text you'll have to buy the book, but the provided sample code gives an example of things existing in C++ and/or Lua and being visible across the scripting/host language divide.
23 Aug, 2009, Erok wrote in the 7th comment:
Votes: 0
Suggest you also look at SWIG and its support for Lua. You can jump right in with it, play around, and then go back into the detailed aspects David has suggested.
03 Nov, 2009, JohnnyStarr wrote in the 8th comment:
Votes: 0
David Haley said:
At some point I will write more about all of this and maybe even give some kind of sample code.

Would you still be willing to do this?

Also, we have gone over Nick's method a bit, and your view of a global Lua state.
Would it be possible to create a lua_State in char_data to handle mob scripting, and then
to add a lua_State to the overall system to be able to add additional sub systems? For example,
I would prefer to advance ROMs update system to an event handler, and would prefer to use
Lua.

I just bought "Programming in Lua 2nd ed", so perhaps I will be able to answer these questions myself
eventually. It seems the challenge is utilizing the API more so than say the scripting itself. As far as
I can tell so far, it is just as friendly as Ruby :)
03 Nov, 2009, David Haley wrote in the 9th comment:
Votes: 0
Quote
Would you still be willing to do this?

Sure, but I'm not sure how much time I have to come up with a complete example of embedding user data into Lua – I'll see what I can do, though, since I have a lot of code lying around, I just need to get around to cleaning it up and packaging into a nice form. :smile:

Quote
Also, we have gone over Nick's method a bit, and your view of a global Lua state.
Would it be possible to create a lua_State in char_data to handle mob scripting, and then
to add a lua_State to the overall system to be able to add additional sub systems?

If you're going to have a global state that can treat characters as proper values, you don't really need the per-character states. (Note that having one of those for every single mob can get a little hairy: Lua is small, but not that small. :wink:)

Quote
As far as
I can tell so far, it is just as friendly as Ruby :)

Lua doesn't have a standard library anything like Ruby, which is a big problem or a nice feature, depending on what you're doing. I find the syntax to be clearer, but that is probably mostly just habit. (I've written a fair bit of Ruby code, but never really liked its usage of funky symbols; I find that to be an unfortunate holdover from Perl.) I think that Lua is exceedingly nice for writing small, targeted scripting, and it is very easy to embed into a larger application. I will have an example up soon of how I used Lua to parse tile descriptions almost for free.
03 Nov, 2009, elanthis wrote in the 10th comment:
Votes: 0
staryavsky said:
Ok, with all this Lua talk, I am hoping someone could suggest a quick example of it
embedded into a mud.


I've got an initial article on the basics of integrating Lua with a C++ game object at http://gamedevstudent.com/journal/2009/1... and I've got an expanded "Part 2" in the works that goes over higher performance bindings and best practices for binding methods to objects. I'll eventually get to the Part 3 on message and property binding as well. (I've had midterms last week and our project's Engine Proof and TDD finalization this week, so I'm a little swamped atm.)

I do not generally recommend binding generators. I know I'm in a small minority with that opinion, but in my experience they tend to take away a lot of control, introduce a lot of unnecessary overhead, and still require a ton of manual code to make safe… and the manual code is more complex because you're wrestling not only with your C++ app and the Lua API, but now also the bindings API. Ideally C++ would have compile-time reflection and meta-programming support and make binding to a script engine with custom control dead easy, but alas, it does not. Binding a method to Lua is very easy though. The hardest part that most people get wrong is the safe handling of the game object reference, which the above article covers.

A good game object design has very few object methods anyway, since you generally want to aim towards generic components and messages, http://cowboyprogramming.com/2007/01/05/..., so manual binding of methods is not nearly as much work as it sounds. Especially if your C++ messages are generic containers (I've seen game engines that just attach a type ID and a Lua table to a generic Message object) and your C++ game objects have property setters and getters (which you desperately want for game editing, debug introspection, and behavior tweaking even if you're not using a script engine at all).

Quote
I think that Lua is exceedingly nice for writing small, targeted scripting, and it is very easy to embed into a larger application.


That's because that's what is was designed for. Lua was primarily a data file format, and a scripting engine second. Ruby is designed as a Real Programming Language, not a little extension language. You can use either language for either purpose, but frankly, if you want to write a large application in a dynamic language (e.g., and entire MUD engine), I'd opt for Ruby over Lua. However, if I'm going to extend a large C/C++ application, I'd use Lua over Ruby.

No one tool solves all problems optimally.
03 Nov, 2009, David Haley wrote in the 11th comment:
Votes: 0
elanthis said:
Binding a method to Lua is very easy though. The hardest part that most people get wrong is the safe handling of the game object reference, which the above article covers.

Yes, this is my experience as well. It's far more difficult to deal with cross-language references, objects and memory management than it is to expose functions.

elanthis said:
Lua was primarily a data file format, and a scripting engine second. Ruby is designed as a Real Programming Language, not a little extension language.

The historical argument for Lua about not being a "Real Programming Language" is about a decade out of date. Lua's problems do not come from its semantics, syntax or other such things: they come quite simply from not having the scaffolding to make large application development easier (e.g., standard libraries, OO framework, etc.). But what's interesting is that the OO framework can be built; you could pretty much replicate Ruby (or Python or …)'s semantics in Lua if you felt like it when it comes to how they model object orientation. That flexibility is, of course, a double-edged sword, in that you have to write a lot of this code yourself (or find somebody who has done it already).

Anyhow, it's not appropriate to say that Lua is just "a little extension language" if you mean anything other than "it has a small standard library" (like what I just said). I'm not sure you meant anything more, but I wanted to clear this up: a lot of people tend to dismiss Lua as a toy language that isn't as "powerful" in terms of semantics because of its very early history.
04 Nov, 2009, elanthis wrote in the 12th comment:
Votes: 0
Quote
Anyhow, it's not appropriate to say that Lua is just "a little extension language" if you mean anything other than "it has a small standard library" (like what I just said). I'm not sure you meant anything more, but I wanted to clear this up: a lot of people tend to dismiss Lua as a toy language that isn't as "powerful" in terms of semantics because of its very early history.


Lua is powerful. It is a complete language with every feature a language needs to write real software.

It's still unoptimal to use it for general programming when you can use Python, Ruby, PHP, Perl, Java, C#, or any number of other languages that are far, far, far better for such things. It is far more than just the lack of a standard library. The lack of a defined object model is actually a huge WEAKNESS, not an advantage, because out in the real world people don't want to have to write custom object models, they don't want to have to integrate multiple libraries using incompatible object systems, and they do want to have a ton of documentation on how the object model works with examples and libraries and ready-to-go software. People don't want to "roll their own" for general programming. That's something you want when you're writing an extension language. It's not something you want when you're writing a big application comprised of many components and third-party libraries. Not even a little.

You like Lua. I like Lua. The majority of the game industry likes Lua. That doesn't change the fact that Lua has severe deficiencies as a general programming language, and we WANT those deficiencies between "fixing" them would make it a less appealing extension language. :)
04 Nov, 2009, KaVir wrote in the 13th comment:
Votes: 0
elanthis said:
Lua is powerful. It is a complete language with every feature a language needs to write real software.

A little off-topic, but has anyone tried using Lua for player-written scripts? They'd need to be run in a sandbox, which would obviously have to handle things like infinite loops and such. It'd be pretty cool for player-generated content though.
04 Nov, 2009, David Haley wrote in the 14th comment:
Votes: 0
OK Elanthis, so you're saying basically the same thing I've been saying re: stdlibs and OO (although you phrase it as a disagreement, which I think is a little weird). When you said it wasn't a "Real Programming Language" you made it sound like there were things it simply couldn't do that other languages can. I've never advocated using it as a general purpose language; in fact, in many threads, I've said that people shouldn't use it to write full applications precisely because its stdlib is so small and lack of standard OOP scaffolding.

KaVir said:
A little off-topic, but has anyone tried using Lua for player-written scripts? They'd need to be run in a sandbox, which would obviously have to handle things like infinite loops and such.

I've toyed with the idea but haven't let it loose in the wild. Sandboxing by removing functions is extraordinarily easy as you can define the global environment for functions. Dealing with infinite loops is a little more interesting but still possible, as you have hooks into the interpreter for instruction count. You can therefore keep an eye on how long the script has been running, and cut it off after so many instructions have been executed.
04 Nov, 2009, JohnnyStarr wrote in the 15th comment:
Votes: 0
KaVir said:
elanthis said:
Lua is powerful. It is a complete language with every feature a language needs to write real software.

A little off-topic, but has anyone tried using Lua for player-written scripts? They'd need to be run in a sandbox, which would obviously have to handle things like infinite loops and such. It'd be pretty cool for player-generated content though.

Aardwolf does here. Not sure if they've opened up building to the public.
09 Nov, 2009, JohnnyStarr wrote in the 16th comment:
Votes: 0
David:
You mentioned that Nick's idea for assigning a Lua state to each character had some drawbacks.
I was wondering what your reasons for this were, and what you have found to be more practical.
Were you planning on using a global state that all objects share? I'm still learning Lua, but I'm pleasantly
surprised at just how easy going the process is. I would like to understand more about it. Ultimately, I'm
planning on releasing a Lua scripting system that can be easily ported to ROM, but that is going to take
some time I think.
09 Nov, 2009, David Haley wrote in the 17th comment:
Votes: 0
There's a lot of discussion in this thread. Perhaps more than you wanted to read, though. :smile: You should skip the first (long) post if you want to get to the discussion; that's where he outlines what he did and how to do it yourself. Most of the discussion you'd be interested in is on pages 1 and 2. (I find it scary that all this happened more than two years ago. Time flies very quickly when you're graduating, getting a job, etc.; I wish I had had more time to work on this stuff in the meantime. Oh well.)

In short, the problem with attaching things to players is that everything becomes player-centric. How do you do AI for mobs that are in rooms next to players? You could argue that the player state would have to go update rooms nearby as well. But what if there are several players? Now you have to deal with deciding which one runs the real update. What about mobs that are 5 rooms away? Is each player going to be independently running AI for all rooms in a 5-room radius?

How about things that need to happen whether or not there are players in the vicinity? Darkstone has some passages open or close depending on whether it's night-time or day-time. That needs to happen whether or not a player is there at the instant of time change. It would be bad if a player showed up a few game hours later and the change had not occurred.

What if you want to have Lua script for mob AI? Are you going to load up a state per mob? That would get silly-big in terms of memory usage.

There are bigger problems, too, than just inconvenient problems like deciding which player runs nearby mobs' AI routines. How do you do things like loop over all players in a room? Since you don't have any handles to players, you can end up with very awkward loop structures, or even some things that become so awkward that they're effectively not worth doing. There would come a point where you might as well be writing mudprog. In post 2 of page 2 of that thread, I give an example of a script that actually runs in a dinky little language I wrote a few years ago that illustrates what is possible on top of mudprog that would be rather difficult in a one-state-per-player approach.

Now of course the one-state-per-player approach has advantages, namely simplicity. You don't have to worry about memory management for your cross-language references. If you have all these references to C pointers floating around in Lua, then what do you do when the C pointer gets destroyed? Lua now has an invalid pointer and dereferencing it will cause something bad to happen. Solving this involves some trickery and care; search for "id system" on page 1 of the thread and you will see some discussion there. Basically you can add your own memory management layer in between the two. This is what I've been experimenting with on Darkstone and it works nicely.

I think that Nick's system is a very, very good way of just getting started and getting things up and running. Using it, he implemented a tasks system and some other stuff as well. I think that if you wanted to use Lua as a more global scripting system for the game, similar to mudprogs, you'd need to expand it. In fact, he did exactly that when he ended up scripting resets in Lua (I think I linked to that thread elsewhere here): he created a global state to track the resets. The drawback to my suggestion is that it's more complicated and requires more up-front work. But, I believe that the flexibility it gains you in the end of the day outweighs the one-time initial cost.
09 Nov, 2009, JohnnyStarr wrote in the 18th comment:
Votes: 0
Nice link!

But I had a totally different idea in mind:
I thought, if you have a lua_State pointer for each mob, that was null by default.
Then, once a trigger is fired, then it opens a new state, runs the source for the script
then the state is destroyed. So, yes you may have 10,000 mobs, but if you have an average
of 25 - 30 players, how many of them are going to encounter players every hour?

Now, this approach is logical to me, but I am not yet an expert.
I do not yet know the overhead of initializing / destroying a state. Also, you lose the
ability to keep track of the objects state in Lua, however, I don't see this as much of
an issue because you can do this in C already.

Nick's example seems to rely on "hooks" to the active state, which is not something i've
studied up on, so i'm sure there is still a lot for me to learn. How does my idea sound
so far?
10 Nov, 2009, David Haley wrote in the 19th comment:
Votes: 0
Creating a state isn't too expensive if all you're doing is creating a state; loading all the libraries can be expensive depending on how many you have to load. I think that the Lua state with standard libraries costs some 500k; that's small for just one state, but it can add up.

But there are other potential problems with this approach. Let's say you want a time-based trigger such that every 5 seconds, the mob casts heal on each individual. How do you do this? You might have a function that returns a list of names, and then you cast on each name; ok. What if you want to heal them only if their HP is less than 50% of their max HP? You can have a function like GetHP(name) that takes the name of the character and returns the HP; you'd need GetMaxHP too of course. What if the character is a mob? You can't necessarily use just the name then, because that could be ambiguous.

What if you need to use names of things in different rooms entirely? When you translate that name to a character object, how are you going to search the character list? Are you going to search the global list, or the rooms nearby, or …?

It's worth noting that you could treat this string identifier as a "handle" to the mob, that must be translated into an actual C pointer behind the scenes. This would be rather similar to having a Lua object that simply represents that identifier, really. The difference is in the syntax; personally I think that things like ch.hp look a lot nicer than GetHP(ch_name).

Also it's worth noting that not all triggers are based on player activity. What about triggers based on time? other mobs? random actions? etc.
Finally, how do you know if a mob has a trigger set up without examining its state to find a trigger handler? You now need to track trigger availability in two places: in the state itself, and then in some global non-Lua place.

Really, it might be easier to have a single global state that takes care of mobs; when you run a function for a mob you'd have a first parameter that is its raw C pointer maybe; you'd just have to be extremely careful about storing that pointer because it can easily become invalid.

This is a case where dynamic languages can be your friend but it's also easy to shoot yourself in the foot. You really don't want to hold on to that C pointer in Lua without being very careful, because if you're not, you might end up with a pointer to invalid memory…
10 Nov, 2009, JohnnyStarr wrote in the 20th comment:
Votes: 0
DavidHaley said:
This is a case where dynamic languages can be your friend but it's also easy to shoot yourself in the foot. You really don't want to hold on to that C pointer in Lua without being very careful, because if you're not, you might end up with a pointer to invalid memory…

Food for thought. I much like the idea of an id system for this issue. I also like the ability to access
a Lua function from the state pointer, like Nick's "call_lua_function" idea.
0.0/125