03 Aug, 2009, Kintar wrote in the 21st comment:
Votes: 0
flumpy said:
Yes. You don't need to do the core as groovy. My core is Java, not Groovy at all. Its faster that way. Groovy for scripting the mud, Java for running the core threading and the telnet stuff.


Yeah, not sure if I was clear in my original post. The core system (telnet, command processing thread, etc.) was Java, but the scripts that were executed for events and commands were implemented as proxy objects that could wrap either compiled java code or a groovy script. In the example I was giving, I renamed the actual command logic class from WhateverItWas.java to WhateverItWas.groovy and recompiled. My build scripts didn't bother compiling groovy files, so the scripting system could no longer find WhateverItWas.class, and so looked for the .groovy file to pick up and wrap. Upon changing the implementation of the command from a compiled Java class to a Groovy script, the time delay came into effect. And the truly strange bit was that this only happened for one or two scripts, not for all of them. Like I said; probably something I was doing wrong in the script itself – something Groovy just didn't like – but annoying nonetheless. :)

flumpy said:
… I've actually implemented a "mobprog" in groovy, as a DSL. Again if you need some help…


Now that definitely sounds like something I'd be interested in! =) I've actually perused the GoogleCode repository for GroovyMUD in the past, but never really looked at it. Once I've got my component system woes sorted out (or when I give up and decide to use Groovy for the component system after all :wink:), I'll come back and take a deeper look!
03 Aug, 2009, Chris Bailey wrote in the 22nd comment:
Votes: 0
I firmly believed that I could make an excellent example of the functionality I thought you were looking for in Ruby. I have been working on it for several days now but I've been unable to do so due to the complications that arise when trying to dynamically load and unload modules. I give up. :P
03 Aug, 2009, flumpy wrote in the 23rd comment:
Votes: 0
Kintar said:
And the truly strange bit was that this only happened for one or two scripts, not for all of them. Like I said; probably something I was doing wrong in the script itself – something Groovy just didn't like – but annoying nonetheless. :)


I'm guessing its probably something to do with dependent scripts… scripts that import other scripts that reference the self same script. The compiler used to get very confused over that sort of thing… try the newer version of groovy, they are a lot better.

flumpy said:
… I've actually implemented a "mobprog" in groovy, as a DSL. Again if you need some help…


Now that definitely sounds like something I'd be interested in! =) I've actually perused the GoogleCode repository for GroovyMUD in the past, but never really looked at it. Once I've got my component system woes sorted out (or when I give up and decide to use Groovy for the component system after all :wink:), I'll come back and take a deeper look!

Well actually it was quite easy and I can tell you what I did in a couple of sentences. I have a bunch of scripts that run commands using a CommandInterpreterobject. I then use the methodMissing method to refer to the command interpreter if it cannot find the command on the mudobject:

mob.say "hi there"
mob.wield "sword"


Easy :D
03 Aug, 2009, David Haley wrote in the 24th comment:
Votes: 0
flumpy said:
David Haley said:
In a sense, you have Java's type system, and you are implementing your own type system on top of it. It's important to remember that Java's types do not have to map directly to the types in your game logic.

Hmm. Yes, but Groovy (and other scripting languages) have already done this for you. You don't need to go reinventing the wheel.

My point though was that there doesn't have to be a direct mapping like this. It can be dangerous to conflate in game objects and types with the programming language's objects and types. It's all fine and dandy for small systems, but when you're working with very, very large ones with all kinds of things happening and very many types, having the layer in between can keep things sane to a certain extent.
03 Aug, 2009, Kintar wrote in the 25th comment:
Votes: 0
Chris Bailey said:
I firmly believed that I could make an excellent example of the functionality I thought you were looking for in Ruby. I have been working on it for several days now but I've been unable to do so due to the complications that arise when trying to dynamically load and unload modules. I give up. :P


Hehe, yeah. If you don't have to worry about statically typed methods, then the real bitch of dynamically loading/unloading modules (in my opinion) is in retaining the state of components that originated in a module as it's reloaded. If your component system is set up right (and this took me several tries before I found anything that even remotely worked in my Groovy-based system), then you can keep loose coupling between the modules themselves and your core component system code, so all you have to do (ALL!?) is provide a mechanism for copying the field data from the components instantiated under the old classloader into new instances created by the new classloader. It's not quite as hard as it sounds, but it is terribly, horribly tedious. My version ended up looking something like:

Basic Setup:
Entities hold pointers to their components.
Components hold the ID of their associated entity.
Entity factory has find(id) method so the Components can locate their entity instance.
Entities and the entity factory are loaded from ClassLoader 0.
Components are loaded from ClassLoader 1 through ClassLoader n.
Component modules retain a weak reference to every Component instance created.
Logic scripts are loaded from ClassLoader n+1, which dynamically reloads every time a module ClassLoader is altered and can link to classes defined in ClassLoadsers 1 through n.

Reloading:
Module from CL2 is marked for reload.
ClassLoader n+1 (logic scripts) is discarded.
New Module classloader is created.
Module from CL2 asks the component system for a new ComponentState object for each of its non-GC'd Component instances.
Module from CL2 populates ComponentState objects with the field values of its Component instances.
CL2 is discarded.
New module is handed the set of ComponentState objects, which it uses to create new instances of the named Components, and populate their fields with the same objects that were held by the original instances.
Entities have their Component reference updated to point to the new instances.
Logic Script classloader is recreated.
Reload is finished.

See? Nothing to it. :faint:
03 Aug, 2009, Kintar wrote in the 26th comment:
Votes: 0
David Haley said:
flumpy said:
David Haley said:
In a sense, you have Java's type system, and you are implementing your own type system on top of it. It's important to remember that Java's types do not have to map directly to the types in your game logic.

Hmm. Yes, but Groovy (and other scripting languages) have already done this for you. You don't need to go reinventing the wheel.

My point though was that there doesn't have to be a direct mapping like this. It can be dangerous to conflate in game objects and types with the programming language's objects and types. It's all fine and dandy for small systems, but when you're working with very, very large ones with all kinds of things happening and very many types, having the layer in between can keep things sane to a certain extent.


Hmm. I thought I understood what you meant until this post. Are you simply saying that you feel it's best to think of the game type "weapon" as something completely and utterly separate from a C++/Java class definition for "weapon", or am I missing the point?

Also, if you are talking about completely separating the game type from a language artifact, doesn't that either A) impose a limitation on the types that a game type can hold as members, or B) give you a massive job of defining type handling for the member fields on a game type?
05 Aug, 2009, Kintar wrote in the 27th comment:
Votes: 0
I've finally got a workable solution to this whole mess! Sadly, I've lost the ability to reload individual modules, rather requiring the entire set of components to be reloaded, but I don't think it's a huge loss since I've managed to maintain entity state without requiring all that messy (and memory expensive) state copying. Reloading should only be occurring during development or when there's a big new feature set rolling out, so speed isn't a huge issue. (No matter how slow it is, it'll still be faster than taking the mud down, moving in the new executable, and starting it back up.)

The one remaining issue is enforcing a requirement that components can only store references to entities, not to other components. For now, however, I'm going to keep that as a rule that's up to the coder to follow, and worry about getting things wired back up to a point where I have an actual, running, basic MUD again.
15 Aug, 2009, David Haley wrote in the 28th comment:
Votes: 0
Sorry for the delay…
Kintar said:
David Haley said:
My point though was that there doesn't have to be a direct mapping like this. It can be dangerous to conflate in game objects and types with the programming language's objects and types. It's all fine and dandy for small systems, but when you're working with very, very large ones with all kinds of things happening and very many types, having the layer in between can keep things sane to a certain extent.


Hmm. I thought I understood what you meant until this post. Are you simply saying that you feel it's best to think of the game type "weapon" as something completely and utterly separate from a C++/Java class definition for "weapon", or am I missing the point?

Yes. Well, "best" is a strong word. I think that one should not couple too strongly one's game logic with one's code type hierarchy. Type defines interface; how some object responds to pokes at its interface should be separate from the kind of interface that it has. In other words, swords, sticks, apples, goblins and warriors are all just entities that can be manipulated in various ways, and will respond in various ways.

It's easier to map in-game types (weapon, armor, door, …) onto actual classes (WeaponThing, ArmorThing, DoorThing, …). Among other things, it lets you write more specific interfaces. But, this is a loss of generality when it comes to having a general component system, and means that the only game object behaviors that can possibly exist are those that have full host-language types for them.

Some games' scripting languages (or other implementation) define a set of events that can happen to things, as well as a very high-level set of things (game surface, mobile thing, immobile thing). From then on, everything is determined by how an object responds to events.

This isn't to say that you can't have inheritance in this separate "type hierarchy" – in-game objects can still inherit behavior from each other. But that doesn't mean that each inheritance of behavior corresponds to an inheritance in the first degree type system.

In other words, you have a first degree type system (Java's classes, for example) within which you implement a second degree type system (your objects' behaviors). It can make life easy to conflate these, but you pay the price of loss of generality. Depending on your goals, though, that price might of course be much smaller than the benefit you gain from having something quickly.

Kintar said:
Also, if you are talking about completely separating the game type from a language artifact, doesn't that either A) impose a limitation on the types that a game type can hold as members, or B) give you a massive job of defining type handling for the member fields on a game type?

Well, the job is more or less massive depending on the language you are writing both first and second degree type systems in. Dynamic languages make it a lot easier because you simply access members without having to define their existence ahead of time. In Java I suppose you could have something like entity->getInt("hit_points"), entity->getEntity("master"), entity->getEntities("group_members") or something like that, but yes, this is a little clunky. But in a language like Lua, you'd just pick up the attribute and run with it. Of course, you lose type safety at that point.

My biggest challenge is in maintaining the flexibility of the dynamic language while keeping the sanity of having the type checked language. This is something that very highly interests me about Scala: you don't have to define types ahead of time, but it still does inference on your types to make sure that you are using things correctly.



If the first/second degree type system stuff didn't make much sense, it's probably because I'm still formulating the expression in my head and am having trouble formally and succinctly describing it. That, and it's 1am and I've been home sick for two days and am not thinking as straight as I otherwise might have been. :smile:
27 Jan, 2012, kotancode wrote in the 29th comment:
Votes: 0
Quote
BTW: I'd be very curious to see a Scala-based MUD at some point, if for no other reason than I want to see their Actor threading system leveraged to deal with all the message passing that goes on. =)


I've done some initial experimentation with Actor-based MUDs in Scala over at my blog and I'm about to start another round of posting/coding using Akka 2.0 actors.

Check out the posts here.
28 Jan, 2012, Chris Bailey wrote in the 30th comment:
Votes: 0
Interesting read Kotan. I've been wanting to play around with Scala, perhaps I will. =)
29 Jan, 2012, David Haley wrote in the 31st comment:
Votes: 0
Scala is an amazing programming language; I highly encourage you to play around with it.
29 Jan, 2012, Joseph Locke wrote in the 32nd comment:
Votes: 0
In response to one of David H's posts concerning Liao, I would just like to point out that Lua ships with etc/strict.Lua to catch access to undeclared variables within the global namespace. It is remarkably easy to map strict structures with this module enabled using __index metamethods and named arguments. It takes just a little extra work to describe structures in this manner, and incurs very little extra overhead while allowing you to avoid the headaches caused by dynamic typing (generally turning run time crashes into more friendly compile time errors.)
29 Jan, 2012, Joseph Locke wrote in the 33rd comment:
Votes: 0
Meant Lua, not Liao and if it wasn't clear, im saying: strict typing is an easily implemented feature of Lua using metamechanisms already provided with stock Lua.
30 Jan, 2012, David Haley wrote in the 34th comment:
Votes: 0
The 'strict' module addresses a different issue from dynamic typing; 'strict' helps address the lack of variable definitions. Dynamic typing is a different concept.

That said, 'strict' is a great module to use and I would highly recommend that people who aren't using it already start doing so. :smile:
30 Jan, 2012, Chris Bailey wrote in the 35th comment:
Votes: 0
Joseph Locke said:
In response to one of David H's posts concerning Liao, I would just like to point out that Lua ships with etc/strict.Lua to catch access to undeclared variables within the global namespace. It is remarkably easy to map strict structures with this module enabled using __index metamethods and named arguments. It takes just a little extra work to describe structures in this manner, and incurs very little extra overhead while allowing you to avoid the headaches caused by dynamic typing (generally turning run time crashes into more friendly compile time errors.)


I'm missing something here because I'm not sure what you are saying.
30 Jan, 2012, Joseph Locke wrote in the 36th comment:
Votes: 0
David said:
1- it is really, very, awfully nice to have static typing for "core engine" functionality. Lua doesn't allow this.
Lua "allows" for precisely this. Why you would want to write "core engine" functionality in the script language as opposed to the staticly typed host language in the first place is a mystery to me. That said, it is very easy to implement static typing within Lua, using Lua, and that is exactly what im talking about. It is also not at all a new idea; people have been doing this to varying degrees within a wide range of projects. Try googling static typing in Lua.

I don't necessarily believe it's the winning strategy; if you are going to use Lua at all, you should use it for what it is. Its dynamic typing is a strong feature, but some "safety" should be implemented by the coder to fit the needs of the application. If you need to differentiate between nil and an undeclared variable, you need to tell Lua that. If you need static types, or static structs, they need proper forward declarations and to be initialized correctly. Tables and metamethods, tables and metamethods..
30 Jan, 2012, Joseph Locke wrote in the 37th comment:
Votes: 0
As another author has remarked, if you actually care about memory footprint, startup time, and having a lightweight distributable that is easy to embed and plays well with others, Groovy isn't such a great choice. Besides, LuaJIT > JVM :P
30 Jan, 2012, David Haley wrote in the 38th comment:
Votes: 0
Joseph, Lua is not a statically typed language. Ever. The 'strict' module is not static typing. In fact, it has nothing to do with types, but with variable declarations. Declarations are not types.

I'm not sure what you're saying is "very easy" because you're not using the term the usual way, but when people have attempted to force type annotations onto Lua (typically using something like a syntax modification or a token filter) it's certainly not easy.

Quote
Why you would want to write "core engine" functionality in the script language as opposed to the staticly typed host language in the first place is a mystery to me.

Why is this a mystery?
30 Jan, 2012, Joseph Locke wrote in the 39th comment:
Votes: 0
David, your last response made no apparent indication that you read my previous two posts. While I concede where declarations are concerned (a declaration certainly isn't a type), I think I spoke pretty plainly; static types, either for compiler optimizations or code-programmer friendliness, are easy enough to implement as either a modification to the language or, as you alluded to, within the application via syntactic sugar and filters. I'll contribute code to this discussion when I have the chance to use something friendlier than my phone.
30 Jan, 2012, David Haley wrote in the 40th comment:
Votes: 0
OK, I look forward to seeing your code then, because that will clarify things… I think there might be some vocabulary mismatch here.

I don't really consider it to be supported when you have to modify the language itself. That's like saying that C supports type inference if only you modify the compiler to support it.

And to be honest with you, I really do suspect that terms are being misused, because static typing in a dynamic language is a non-trivial project (and somewhat oxymoronic), and is typically only achieved by imposing very strong constraints on the language – resulting in a rather different language entirely.

If it helps you, the specific issues I have with your posts (which, yes, I did read, but thanks anyhow – would you like me to say that you didn't read anything I wrote either because you still don't see what I'm saying? eh):

"If you need to differentiate between nil and an undeclared variable, you need to tell Lua that."
This isn't static typing, this is declaration.

"If you need static types, or static structs, they need proper forward declarations and to be initialized correctly."
Forward declarations aren't static typing, they are making sure that a dynamic structure fits a given constraint.



I suspect that what you are referring to is essentially an extension of the 'strict' module, where you impose certain checks on what's going on. But this is very different from static typing. For example, with 'strict', you can do something like:

local a = "abc"
compute_something(a)
a = 123

but this is not static typing.

Then you have something like this (in pseudocode):

define_type:
my_struct
fields:
name (string)
zipcode (number)

bla = new my_struct()
bla.name = "abc"
bla.foo = "bar" <– error, invalid field

this is also not static typing.
20.0/43