• NOW LIVE! Into the Woods--new character species, eerie monsters, and haunting villains to populate the woodlands of your D&D games.

Open Source d20 API/Engine

Firzair said:
Hi reanjr,
I think there is some more functionality needed from the RPGL:
  • Some kind of SELECT for getting a collection of something used with a kind of FOREACH clause (e.g. Select from Feats where Feats.Type like "Fighter").
  • I think there has to be a scope for each function (e.g. something that says this function belongs to the object creature)

Could this already be done or do you have to implement some more tags?

Greetings
Firzair

As to the first point, there is a way to do it (and I suppose it could be mashed into a function, too; but I hadn't gotten to anything like that yet). Basically, the <a> function can resolve simple XPath like statements and return arrays of data. For instance:

<a>feats.feat:type='Fighter'</a>

Would return an array of all feat elements that are children of the feats element and half a type attribute set to Fighter. Once you have this array, you can use another special resolution mechanism ::

Say that you store the array in a variable called fighter-feats. Then:

<a>fighter-feats::count</a>
Would return the number of elements in the array

<a>fighter-feats::1</a>
Would return the first of them.

So you could fairly easily write a foreach function (and I'm pretty sure I will).

I haven't finalized anything on the way those variable resolutions work yet, but tentatively, the following apply:

Code:
.
Current context

.child
The child of the current context (and so forth like .child.grandchild etc.)  This can be a child element or a property of the context.

:property
A property.  If this is left without any qualification, it just checks if the property exists or not.  You can also append ='value' to evaluate to a property that is set to a particular value.  I use single quotes here for ease of parsing.  Unlike using the .child syntax to select a property, using the :property syntax doesn't evaluate to the property but is used as a means of identifying elements.  (I hope I explained that clearly, I can't tell).

::count
The number of elements in the reference.  Usually 1.

::1, ::2, etc.
A particular element if there are multiple.  Defaults to the first element if unspecified.

[ ]
Anything found in brackets is evaluated as a variable reference then plugged in to its surroundings (<a>fighter-feats::[counter]</a> for instance).
 

log in or register to remove this ad

reanjr said:
Nope...

Code:
<character>
	<feat name="toughness" />
	<feat name="toughness" />
</character>

...or some such thing would work fine.

How could you tell that he has it twice? There has to be some way for this...
And how would I refer to the second one?
 

Firzair said:
Hi reanjr,
I think there is some more functionality needed from the RPGL:
  • Some kind of SELECT for getting a collection of something used with a kind of FOREACH clause (e.g. Select from Feats where Feats.Type like "Fighter").
  • I think there has to be a scope for each function (e.g. something that says this function belongs to the object creature)

Could this already be done or do you have to implement some more tags?

Greetings
Firzair

As to the second point what you do is define functions inside different root elements. For example, stonecunning (the dwarf ability) is defined like so:

Code:
<monsters>
	<function name="stonecunning">
		<text-representation>
			<a>"Stonecunning: automatically search secret doors...blah blah"</a>
		</text-representation>
		<add-conditional-skill-mod skill="search" mod="2" type="racial" reason="stonecunning" />
	</function>
</monsters>

Now in the dwarf data, we write

Code:
<monsters>
	<monster name="dwarf">
		<stonecunning />
	</monster>
</monsters>

When you apply a race to a character (in this case dwarf), all of the stuff in the dwarf element is basically merged into the character element and executed. So you create a character, add dwarf stuff, which triggers stonecunning to execute, which in turn adds a conditional skill modifier to search checks.

So, basically, because the stonecunning function is found inside <monsters>, that is its scope. But once monster data is merged with character data, it allows the character context to use the function.

So, nope. No additional tags needed.

I haven't seen a need for a new tag outside the data tags (create-context, add-data, add-property, delete-data, delete-property, and import-data) in several days, so it seems like a decent set of functions. I will probably have to think of string functionality of some kind, but I might just treat that like an array of chars. "level"::count would be 5 for instance and "level"::3 would be "v".

I think that actually pretty much covers it except for events, which I'll explain here just so that I have talked about it. I'll use the dwarven ability to move at full speed while encumbered as an example, because it's pretty straight forward.

An event is declared in a similar fashion to a function, but it never takes arguments (I don't think, don't hold me to that). It generally handles a simple operation that could easily be done without a function.

Code:
<event name="speed-change" amount="0" reason="">
	<set name=".speed">
		<add>
			<a>.speed</a>
			<a>amount</a>
		</add>
	</set>
</event>

Basically, you can declare a function as normal but set two reserved properties on it: attach and when.

attach indicates an event to attach the function to. when indicates when to run the function in relation to the event: "before" or "after".

So, in the monsters stuff you have
Code:
<monsters>
	<function name="encumbered-movement" attach="speed-change" when="before">
		<assert>
			<e>
				<a>reason</a>
				<a>"encumbrance"</a>
			</e>
			<set name="amount">
				<a>0</a>
			</set>
		</assert>
	</function>
</monsters>

When a character becomes encumbered, you call
<speed-change amount="-10" reason="encumbrance" />

This triggers the encumbered-movement function because it was told to attach to the speed-change event. It was also told to run before the event itself. It checks the reason, which is "encumbrance", and so sets the amount to 0. Then it lets the event run, but since amount has been changed to 0, it doesn't do anything.
 

Firzair said:
How could you tell that he has it twice? There has to be some way for this...
And how would I refer to the second one?

In this case you could use the following to tell you he had it twice:
<a>.feat:name='toughness'::count</a>

And you could use this to refer to the second one:
<a>.feat:name='toughness'::2</a>

The first one could be referred to with either of these:
<a>.feat:name='toughness'</a>
<a>.feat:name='toughness'::1</a>
 

I don't think I talked about conversions. If you have to explicitly treat one type as another, you can do that with the <a> function using its convert property. Convert can be one of the following values:

text: converts number or boolean to text
boolean: converts number or text to boolean
number: converts string or boolean to number
integer: converts to number and then truncates fractional part
lower: lowercase text
upper: uppercase text
is-set: returns boolean indicating whether value is Nothing (I just thought of this so I can get rid of the is-set function.
 

I'm sort of... intrigued by the purpose of RPGML. Out of curiosity, where does it fit compared to the ontology? Is it something that would be generated from it to accomodate specific implementations? (what I term an "intermediate format")

Also, to search, just use XPath or XQuery. I assume you want to do this to load the XML into some form of internal binary representation? From experience, using the XML directly hasn't proved very efficient.

Andargor
 

andargor said:
I'm sort of... intrigued by the purpose of RPGML. Out of curiosity, where does it fit compared to the ontology? Is it something that would be generated from it to accomodate specific implementations? (what I term an "intermediate format")

It's an alternative to the ontology that I support using instead of RDF-OWL. It's much simpler to use RPGML to do the stuff that we'd use RDF-OWL for. The benefit of RDF-OWL (I feel obligated to point out), is that it is a major standard with library support and documentation all over the internet.

RDF-OWL is fairly straight-forward for those familiar with XML and the way XML works. RPG ML is designed to be simple for your average, computer-savvy role-player who, years ago, fiddled with a programming and/or scripting language. In my opinion, RPG ML will lead to a much larger development community than RPG ML. I think RDF-OWL will be intimidating, and keep non-programmers away.

I also point out on the Wiki that it is fairly straightforward to use RPG ML to create a normal scripting language that is translated into RPG ML. That way, Java programmers can have a version of RPG ML that looks very much like Java, rather than using XML to code.

[edit] I also point on the Wiki that is fariyl... man I rarely have that many typos/word ommissions in such a small space...

Also, to search, just use XPath or XQuery. I assume you want to do this to load the XML into some form of internal binary representation? From experience, using the XML directly hasn't proved very efficient.

Andargor

I was going to use XPath, but I decided against it for the reason stated above. A person just picking up on RPG ML can easily understand child/parent realtionships and remember how to use the, but once you get into ancestors, siblings and the more esoteric selectors available in XPath, it can become confusing for someone who doesn't sit down and decide to learn XPath on its own. I have to look up stuff all the time for XPath even though I do understand it. That's not the type of environment I want people to be working in.

Though only initial thoughts, my idea for the engine architecture is to load the main RPG ML file(s) into memory and create a set of (for instance) a collection of functions that contained the text of the RPG ML. I thought of actually compiling the functions on the fly, but RPG ML actually contains language features that a standard programming language can't really handle very well. But by keeping the lists, pointers, variables, etc. stored in the engine and just keeping the RPG ML for function references that can be parsed when called, I hope to gain the best of both worlds (the app doesn't need to parse through a gigantic XML tree to find the function "roll", but it still has to read the 10-20 XML tags contained in "roll" to figure out what it does).

As for data (such as characters, etc.) I do plan on those being kept in XML format. They should be very simple and small snippets, so I don't see performance being an issue. They're just being used as a data store.

I picture the engine having a stack, as to be expected, contexts that the engine is currently running in. A particular context can contain its own unique set of functions and variables. I haven't really looked into it, but I believe a context can only have access to its own local functions and variables and those that are global, so there would be no long walk up the stack to find where something is declared (important as every other RPG ML function call has some sort of variable reference).

I also might experiment with some sort of caching mechanism if it seems to need it.
 
Last edited:


Sure Solomonk,
just head over to the RPGEngine-Wiki. At the moment it's a bit deserted, but I hope that's just due to RL constraints of reanjr and Andargor (I think I saw him posting about some absence du to business).
I myself await eagerly their return as the RPGML functions need some more description.

Greetings
Firzair
 


Into the Woods

Remove ads

Top