I've come up with a design for a feature I call "Dynamic Types" and I'd love some feedback:

The goal of Dymanic Types is to allow an extension to create new types at runtime. For example, this might allow a mod to create a weapon with random properties. As with Betel's suggestion, the way this works is by providing an XML string that describes the type (using all the normal syntax, including embedded code) and adding it as a new type at runtime.

At game-creation time (before we bind UNIDs to structures) we iterate over all template types and evaluate them. In the example above, the UNID "&itRandomWeapon;" will be initialized to the result of the evaluation of the OnEval code. The semantics of OnEval are simple: we expect it to return a string of well-formed XML and we load it as if it were any other type.

Doing this at game creation time has a few advantages:

1. You can use the UNID (&itRandomWeapon;) in any other type (e.g., ship classes) as if it were a normal type.2. I think you can specify an existing UNID (e.g., &itLaserCannon;) which will cause the dynamic type to override the existing one. [there might be roadblocks I haven't thought about.]3. You can generate types (such as SystemMap) that are only used at game-creation time.

[A few notes of the above: First notice that I use the CDATA syntax. That's just standard XML syntax so that we don't have to escape all the angle-brackets (that works in today's XML parser). Second, notice the subst command takes a struct of key/value pairs--this makes the syntax easier, IMHO, and is something that I think I will add in 1.08.]

DYNAMIC TYPE FUNCTIONS

I think the above handles 80% of the use-case, and if people agree, the above might be all I get done in 1.08. But another possible use case is to create types in the middle of the game. For example, imagine that a quest needs to generate a weapon based on an item that the player brings.

We can add the following functions to help:

(unvCreateType UNID string) -> True/Nil

This function takes an UNID (see below) and a string. The string is just some well-formed XML string that could be generated using the subst technique above. If successful, this will register a new type associated with the given UNID. You can then use the UNID in any function that accepts it (e.g., itmCreate).

The type that you create will be persisted with the game.

There are a few limitations:

1. The UNID must be unused (thus, you cannot override a type using this technique, even one that was previously created with the function)2. The kinds of types that you can create is more limited. E.g., you cannot create a SystemType with this technique.

To help generate UNIDs, we need a new functions:

(unvDynamicUNID string) -> UNID

This function works as follows: If "string" has not yet been bound, it generates a new UNID (from the 0xF??????? space) and associates the string with it. If the string has already been bound, it just returns the UNID for that string.

You can now use this function to create new types without having to worry about UNIDs. For example, you can do something like:

I'd love to hear feedback on this design. As I said, I'm leaning towards implementing template types for 1.08 and leaving the dynamic type functions for later, but I'm happy to hear counter-arguments.

Mon Feb 20, 2012 7:29 pm

Betelgeuse

Fleet Officer

Joined: Sun Mar 05, 2006 6:31 amPosts: 1920

Re: Dynamic Types

hmm I like it but have a couple questions.

Would storage.xml be loaded before this allowing us access to data saved there?Would we be able to use typSetGlobalData or something else to communicate between different evaluations? (other than globals of course)I am assuming that it isn't saved in the saved game is this correct?, or do you load the save game when the game first runs so we can do the title screen ships.

_________________Crying is not a proper retort!

Mon Feb 20, 2012 8:03 pm

george moromisato

Developer

Joined: Thu Jul 24, 2003 9:53 pmPosts: 2586

Re: Dynamic Types

Betelgeuse wrote:

hmm I like it but have a couple questions.

Would storage.xml be loaded before this allowing us access to data saved there?Would we be able to use typSetGlobalData or something else to communicate between different evaluations? (other than globals of course)I am assuming that it isn't saved in the saved game is this correct?, or do you load the save game when the game first runs so we can do the title screen ships.

1. Yes, Storage.xml is loaded first, so you can use it.2. typGet/SetGlobalData is a little tricky. You can definitely call it on static types; you definitely can't call it on dynamic types that have not yet been defined. It will probably fail if you try to call it for your own type in the middle of OnEval (but I'm not sure).3. The dynamic types are saved along with the game, so you don't have to re-create them. In fact, you'll get an error if you try to redefine them.

To say the least, this is very, very cool. I can do some more fancy things for wyvera & the tinkers (TSB) with this.

_________________(shpOrder gPlayership 'barrelRoll)

Tue Feb 21, 2012 6:07 am

Betelgeuse

Fleet Officer

Joined: Sun Mar 05, 2006 6:31 amPosts: 1920

Re: Dynamic Types

one question, what happens when you start a new game when your old game had dynamic types defined? Would it be locked into those? Or would things that are dynamic type dependent not be on the title screen (then when are they bound)?

This looks very cool George. What a lot of fun we can have with this! :)

Personally I think the dynamic type functions sound most exciting, but I have no argument for why we should have those first. One question I do have about them though, is if the xml you must provide can be a string. So, "<ItemType ...>...</ItemType>"?

Other than that I can not think of anything that has not already been brought up. Except that, wow, I seriously need to get modding again once 1.08 comes out. So many cool new toys. Thanks! XD

one question, what happens when you start a new game when your old game had dynamic types defined? Would it be locked into those? Or would things that are dynamic type dependent not be on the title screen (then when are they bound)?

When you press "New Game" all dynamic types are reset to initial conditions (whatever the adventure/extensions define).When you press "Load Game" the dynamic types are initialized to whatever the saved game specifies.[That is, dynamic types are bound to the game and do not "leak" from one game to another. If you want to share dynamic types across games then you can use Storage.xml for that.]

Tue Feb 21, 2012 6:19 pm

george moromisato

Developer

Joined: Thu Jul 24, 2003 9:53 pmPosts: 2586

Re: Dynamic Types

alterecco wrote:

This looks very cool George. What a lot of fun we can have with this!

Personally I think the dynamic type functions sound most exciting, but I have no argument for why we should have those first. One question I do have about them though, is if the xml you must provide can be a string. So, "<ItemType ...>...</ItemType>"?

Other than that I can not think of anything that has not already been brought up. Except that, wow, I seriously need to get modding again once 1.08 comes out. So many cool new toys. Thanks! XD

Turns out that creating a new function was easier than doing the TemplateType, so I did that first to test. And you can use a string. Here is an example that I just tested:

The CDATA syntax is just so that I can use angle-brackets in the string. And notice also that I used single-quotes instead of double-quotes for the attributes. I believe this is supported by standard XML and it makes it easier to embed in a string.

What I'm really after is nonrandom templatetype. A fully random weapon can get completely out of balance so I want to be able to eg. generate a damage string then generate a firerate subject to additional constraints based on the damage string then generate a power use dependent on the exact damage and firerate.

And then I want to be able to make another weapon dependent on the first. Suppose the first is my randomization of the Turbolaser. I want to be able to generate a dual turbolaser and omni turbolaser with stats based on the turbolaser.

To do this I need to either be able to overwrite static types with unvtypcreate or embed translisp in templatetype and control or at least predict the order of evaluation of templatetypes. (If they evaluate in UNID order I can do the actual randomization on whichever base type has the lowest UNID. If they evaluate in file order within a file I can put the simplest version first. Except possibly the Moskva line I think the simplest version always has the lowest UNID anyways.) I'm pretty sure if unvtypcreate is able to overwrite static types I can control the order by placing them in a block.

What I'm really after is nonrandom templatetype. A fully random weapon can get completely out of balance so I want to be able to eg. generate a damage string then generate a firerate subject to additional constraints based on the damage string then generate a power use dependent on the exact damage and firerate.

And then I want to be able to make another weapon dependent on the first. Suppose the first is my randomization of the Turbolaser. I want to be able to generate a dual turbolaser and omni turbolaser with stats based on the turbolaser.

To do this I need to either be able to overwrite static types with unvtypcreate or embed translisp in templatetype and control or at least predict the order of evaluation of templatetypes. (If they evaluate in UNID order I can do the actual randomization on whichever base type has the lowest UNID. If they evaluate in file order within a file I can put the simplest version first. Except possibly the Moskva line I think the simplest version always has the lowest UNID anyways.) I'm pretty sure if unvtypcreate is able to overwrite static types I can control the order by placing them in a block.

I think I get it.

TemplateTypes within an extension are guaranteed to evaluate in UNID order. [Eventually, I will probably have to alter the evaluation order of each extension based on dependencies. For example, if extension B depends on extension A, then TemplateTypes in extension A need to evaluate first, regardless of UNID.]

I should create an event that fires before any TemplateType is evaluated (something like <OnGlobalInitTypes>). You could create all your randomizations there in the proper order (and store them in global variables or whatever). Then all your TemplateTypes (for the turbolaser and dual turbolaser) can refer to the globals. Then you don't care what order the TemplateTypes get evaluated in.

It would also be pretty easy for me (I think) to allow OnGlobalInitTypes to call unvCreateType to override static types (this would be the only event in which you could do that). Then you can do all the work in script without any TemplateTypes.

p.s.: Now I know why you want this: http://wiki.neurohack.com/transcendence/trac/ticket/741 (which is unfortunately not that easy). If you could extract the XML from an existing type you could alter it and create a new type. For example, you could have a function that creates an omni version of any existing weapon.

Tue Feb 21, 2012 8:52 pm

george moromisato

Developer

Joined: Thu Jul 24, 2003 9:53 pmPosts: 2586

Re: Dynamic Types

Wolfy wrote:

Will we be able to change the stats once set? And if not, can we delete old ones so that we don't waste our UNID space?

No, not within a game, unfortunately. [Nor can we delete them, since we would have to search through all systems looking for references to the type you deleted--or risk a crash.]

But don't worry about UNID space. You can call unvDynamicUND more than 250,000,000 times before it runs out of UNIDs (it allocates UNIDs out of the reserved 0xF??????? space). [And this is a per-game limit--if you start a new game, the limit resets.]

Who is online

Users browsing this forum: No registered users and 0 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum