Looking for a scripting language especially for a rpg

Hi,
first I want to mention that I already checked custom controllers and Groovy but
I am not completely sure if they fulfill my requirements or how to use these
tools to fulfill the requirements.

I am researching for a scripting language especially for rpgs. The thing I am worrying about is that
the script has to run some kind of asyncronically without the use of threads (which would add a lot of complexity
to my project regarding synchronizing). For example, if a npc gets the commands
wait(30);
goTo(Position);
the main program may not block., so I was looking for alternatives and I found

In case you dont want to read the whole article, the action list stores a list of actions, each one has got a duration,
so if the update method is called ( with the execution time as parameter) and the duration exceeds (or another goal
is reached for example if the walk goal is reached), the list proceeds to the next action.
I would like to combine this method with the usage of scripts, so the quests and story will be user editable from an editor.

The problem is that those scripts dont work asyncronically at all. For example,
if I extend the upper script

wait(30);
if (questState(“quest1”)> 5) goTo(Position); else goTo(Position2);

the quest state will be checked while executing the script, not after waiting 30 seconds.

I am interessted if any scripting language exists that takes time-based behaviour into account.
Another must have feature is the ability to serialize the execution state of the script, so that
the game can be saved at any time. So if you have any ideas about such a script language,
please enlighten me.

You may need to separate the idea of the action queue from the script being run. Neverwinter Nights did this. You could run functions directly or you could run them as actions. Groovy (or anything with closures really) would make this pretty easy.

[java]
wait(30); // which is really just adding a wait action
action {
if( questState(“quest1”) > 5 ) {
goto(position)
} else {
goto(position2)
}
}
[/java]
…where the action function would add that closure to the action stack after the wait. When executed it would add the goto() actions to the stack and so on.

In this way, you could have both code and queued actions. In the above example, the goto()s might add to the end of the queue or perhaps you have a clearAllActions() which resets the queue to ‘interrupt’ what is already happening. Useful for the rest of the AI state machine that may want to interrupt what is going on if attacked or an enemy is spotted, etc…

1 Like

Erm. So you want threading without having threads? Sorry to break it to you but you need threads for threading.

The alternative is to remove the wait, break it into 2 chunks and only trigger the 2nd chunk as appropriate.

@umask007 said: The thing I am worrying about is that the script has to run some kind of asyncronically without the use of threads (which would add a lot of complexity to my project regarding synchronizing).

All threads run async (at least in regular java, and I do not think they changed anything here). To add synchronisation you need to add locks or what ever you need to make it synchronized.

This means you can use threads to run your code? :slight_smile:

Thank you for your answer, @pspeed. Looks like a good solution to me.
I still have to check for Java and Groovy interoperability, because closures
dont exist in java.

@zarch, I dont need threads, just a way to execute scripts that dont block. The action list
pattern described at the link I posted is a way to do it.

@netsky
Using Threads would also work, but it would add a lot of synchronizing problems and it would
be a very difficult task to de/serialize the execution state of the scripts.

Putting synchronized everywhere is not a solution to get a predictable logic flow with multiple threads. Using wait(80) for a NPC isn’t either, it could not even evade a blow just because its waiting…

4 Likes
Putting synchronized everywhere is not a solution to get a predictable logic flow with multiple threads. Using wait(80) for a NPC isn’t either, it could not even evade a blow just because its waiting..

Thats a good point. A lot of games solve it by making important npcs invincible. I guess this will suffice for my game, unless you know an easy way to implement it.

@umask007 said: Thats a good point. A lot of games solve it by making important npcs invincible. I guess this will suffice for my game, unless you know an easy way to implement it.

oO huh? No, few games have this limited scripting. Maybe you go through the jME tutorials to see how you can create a game based on an update loop so you don’t need to look for solutions like these. Using wait() in any programming really is only used to test or demonstrate things.

One way to only do a thing after a certain time has elapsed with an update loop is this:

[java]float curTime = 0;
public void update(float tpf){
curTime=curTime+tpf;
if(curTime>1){
//do stuff here
}
}[/java]

Guys, the action queue does not preclude the action queue from being cleared.

This is exactly the way Neverwinter Nights did their scripts/AI… and it works fine. wait(30) is just an action in the action queue… which is like a to-do list of things the NPC will do next. Any of the other incoming events can clear the action queue as needed.

This is so common I’m surprised we’re arguing about it.

@pspeed said: Guys, the action queue does not preclude the action queue from being cleared.

This is exactly the way Neverwinter Nights did their scripts/AI… and it works fine. wait(30) is just an action in the action queue… which is like a to-do list of things the NPC will do next. Any of the other incoming events can clear the action queue as needed.

This is so common I’m surprised we’re arguing about it.

Lol, you are arguing about that ^^ I don’t think the OP quite gets the difference between a “script that doesn’t block” and an action queue :wink:

@normen said: Lol, you are arguing about that ^^ I don't think the OP quite gets the difference between a "script that doesn't block" and an action queue ;)

Well, since he specifically mentioned action queues I thought I’d help him learn that part without telling him that what he wants to do is impossible.

I think action queues are much easier to understand than the alternative of a scripting language supporting continuations/coroutines, etc… which actually would make the script work fine as written since the wait(30) would effectively put the script to sleep while that thread goes on to do something else. but a) I’m not very familiar with Java-based scripting languages that support coroutines and b) I think they are harder to figure out what’s going on… and finally, c) I think they are way harder to “interrupt” properly.

…where as groovy is trivial to integrate with Java and would easily support an action queue with closures as I included above. Just need the right API glue. It even plays nice with state machines since if the state machine has something like a global state then it can just pop the actions off as needed letting the rest of the state machine do the work.

oO huh? No, few games have this limited scripting
In the majority of games, npcs arent even attackable at all. If they are you need a lot more scripting. What happens if a npc dies that is important for the continuation game? You have to script alternatives for the affected quests. Its true I didnt think much about the integration of the KI yet. In my opinion, the easiest way to do it is just to switch off the KI while the action list is not empty. It wont block anything if its empty. Thats a small limitation considering I will use the action list for moving nps during quests most of the time.

What about actions for NPCs that fight tho?

For example its quite common for a big bad to come in and do something until/unless players interrupt.

well a scripting system could certainly be run “asynchronously” without using multiple threads. I made a scripting system for the game I’m working on to define up to 2000 missiles to shoot, where, when, how often, and in what order. and it’s merely just an AppState that uses the game update loop.

I could show you some of the scripting system but it largely wouldnt be of use to an RPG game (or probably really any game besides Dodge). but the same principles would apply.

  1. FIrst you need to make sure any scripted actions are doable via pure java code.

  2. Then you come up with plaintext file format that you can parse

  3. then feed your parsed values in to the java methods which you’ve already made in step 1.

Creating scripts is easy, the hard part is you first need to write the actual code that the scripts work with. (creating your game so characters know how to walk to a coordinate, know when theyre at their destination, when theyre dead, when enemies are near, when player is attacking them) so you can then have a scripting language that is just a list of waypoints, actions, and attributes.

@icamefromspace said: 1. FIrst you need to make sure any scripted actions are doable via pure java code.
  1. Then you come up with plaintext file format that you can parse

  2. then feed your parsed values in to the java methods which you’ve already made in step 1.

…and you could do all of that in groovy and not have to write your own parser…

true, though what groovy can do is probably far beyond what is really needed, and non programmers probably won’t be comfortable with it.

All that is really needed to be the “script” is something like this.

[java]
//Defining a characters attributes
Character Bob:
Inventory:
hat
shoes
Strength:
10
Smarts:
15
Speed:
10
Spawn Location:
xyz
[/java]

[java]

Routine Idle{
Walk to coordinate xyz
Pick Nose
Walk to coordinate xyz
Check watch

}

Routine NearEnemy{

}

Routine LowHealth{

}
[/java]

If your scripts involve calculating paths, distances, colors, attack damages, etc then its not really a script, its just game code that is compiled after the rest of the game code.

The Groovy could look almost exactly like that (even cleaner) and you could avoid forcing them to learn keywords like “Routine” that would be completely useless knowledge in any other scripting language.

Game programmers as a rule have a huge “not invented here” blind spot for scripting languages.

Using the java scripting api stuff would get quite more simple

ScriptEngine engine = new ScriptEngineManager().getEngineByName( “groovy” );
System.out.println( engine.eval( “(1g…42g.gcd(56g)).sum()” ) ); // 105
eg for groovy, alsow orks with javascript and a few dozen other langues if you have a engine for it.

Or a javscript example
http://www.javalobby.org/java/forums/t87870.html

Just did a quick groovy test and I am really inpressed by its ease of use.
The java/groovy interoperability is really awesome, I recommend anyone
interessted in scripting to try it out. It is very easy to call java code
from a groovy script, the java syntax is compatible to groovy( with even some
degree of freedom, like skipping bracers or semicolons).

[java]
/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package mygame;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

/**
*

  • @author heizi
    */
    public class GroovyTest {

    public int testValue;

    public static void main(String[] args) {
    GroovyTest gt = new GroovyTest();
    gt.testValue = 1;

     Binding binding = new Binding();
     binding.setVariable("foo", new Integer(2));
     binding.setVariable("gt", gt);
    
     GroovyShell shell = new GroovyShell(binding);
    
     Object value = shell.evaluate("gt.test();gt.testValue++;println('Hello World!'); x = 123; return foo * 10");
     System.out.println(value);
     System.out.println(binding.getVariable("x"));
     System.out.println(gt.testValue);
    

    }

    public void test() {
    System.out.println(“sddfsafsd”);
    }
    }

[/java]

If you want to try it out, the groovy plugin is easy installable in the Jmonkey SDK (Tools->plugins).

You don’t even have to import the groovy stuff directly since Java includes script engine support by default. You just have to have the groovy-all jar on the classpath and tell the Java ScriptEngine stuff that you want groovy.

For example:
[java]
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName(“groovy”);
engine.setBinding(“foo”, new Integer(2));
engine.eval(“print foo”);
[/java]

Edit: oops, I shortened the setting of the binding, but you get the point. Here is a full example I use to load styles in lemur: http://code.google.com/p/jmonkeyplatform-contributions/source/browse/trunk/Lemur/src/com/simsilica/lemur/style/StyleLoader.java

1 Like