Veracity's Property Management Library - vprops.ash

Veracity

Developer
Staff member
If we can have "zlib", why not "vprops"? :)

This is a package of functions to make it easy to store and retrieve simple and complex datatypes in properties. It was inspired by the desire to let my script define all of its configuration variables with default values and associated properties, allowing the script user to either edit the script to change the default or set individual properties for specific users to override one or more defaults, but having actual properties set in your preferences file only if they override the script's default.

If I have 50 script variable and you override 3 of them for user A and 2 for user B, user A will have 3 properties and user B will have 2.

And it exists!

Code:
git checkout Veracity0/vprops

Here is documentation, of sorts:

Code:
since r17892;

// Properties are mappings from string to string: a (string) name has a (string) value.
//
// The string value can represent one of the following simple ASH data types:
//
// "string"
// "boolean"    boolean to_boolean( string ); string to_string( boolean );
// "int"    int to_int( string ); string to_string( int );
// "float"    float to_float( string ); string to_string( float );
// "item"    item to_item( string ); string to_string( item );
// "location"    location to_location( string ); string to_string( location );
// "class"    class to_class( string ); string to_string( class );
// "stat"    stat to_stat( string ); string to_string( stat );
// "skill"    skill to_skill( string ); string to_string( skill );
// "effect"    effect to_effect( string ); string to_string( effect );
// "familiar"    familiar to_familiar( string ); string to_string( familiar );
// "monster"    monster to_monster( string ); string to_string( monster );
// "element"    element to_element( string ); string to_string( element );
// "phylum"    phylum to_phylum( string ); string to_string( phylum );
// "coinmaster"    coinmaster to_coinmaster( string ); string to_string( coinmaster );
// "thrall"    thrall to_thrall( string ); string to_string( thrall );
// "bounty"    bounty to_bounty( string ); string to_string( bounty );
// "servant"    servant to_servant( string ); string to_string( servant );
// "vykea"    vykea to_vykea( string ); string to_string( vykea );
//
// They can also represent collections of those simple types:
//
// "list" -> TYPE [int] - an ordered collection, allowing duplicates.
// "set" -> boolean [TYPE] - an unordered collection with no duplicates
//
// Collections are put into strings by listing them in the natural order
// of the key, separated by a delimiter character. By default, the
// delimiter is "|", but "," or ";" or anything else can be used
//
// (Internally, this uses split_string(), which takes a regex, not a
// string. Since "|" is a special character in a regex, for convenience,
// we turn "|" into "\\|". But you are welcome to use an actual regex,
// rather than a "delimiter character" if you wish.)
//
// Since the key of a "list" is an int, the elements of the list are
// ordered and duplicate values are allowed.
//
// Since the key of a "set" is any datatype, the elements of the set
// are not ordered and duplicate keys are not allowed.

// You can use the appropriate built-in ASH function to convert between
// simple ASH data types and a string, or vice versa, as listed above.
//
// This package provides coercion functions for "list" and "set" types.
// The versions without "delimiter" assume "|".

// Sets:

boolean [boolean] to_set_of_boolean( string set, string delimiter );
boolean [boolean] to_set_of_boolean( string set );
string to_string( boolean [boolean] set, string delimiter );
string to_string( boolean [boolean] set );

boolean [int] to_set_of_int( string set, string delimiter );
boolean [int] to_set_of_int( string set );
string to_string( boolean [int] set, string delimiter );
string to_string( boolean [int] set );

boolean [float] to_set_of_float( string set, string delimiter );
boolean [float] to_set_of_float( string set );
string to_string( boolean [float] set, string delimiter );
string to_string( boolean [float] set );

boolean [string] to_set_of_string( string set, string delimiter );
boolean [string] to_set_of_string( string set );
string to_string( boolean [string] set, string delimiter );
string to_string( boolean [string] set );

boolean [item] to_set_of_item( string set, string delimiter );
boolean [item] to_set_of_item( string set );
string to_string( boolean [item] set, string delimiter );
string to_string( boolean [item] set );

boolean [location] to_set_of_location( string set, string delimiter );
boolean [location] to_set_of_location( string set );
string to_string( boolean [location] set, string delimiter );
string to_string( boolean [location] set );

boolean [class] to_set_of_class( string set, string delimiter );
boolean [class] to_set_of_class( string set );
string to_string( boolean [class] set, string delimiter );
string to_string( boolean [class] set );

boolean [stat] to_set_of_stat( string set, string delimiter );
boolean [stat] to_set_of_stat( string set );
string to_string( boolean [stat] set, string delimiter );
string to_string( boolean [stat] set );

boolean [skill] to_set_of_skill( string set, string delimiter );
boolean [skill] to_set_of_skill( string set );
string to_string( boolean [skill] set, string delimiter );
string to_string( boolean [skill] set );

boolean [effect] to_set_of_effect( string set, string delimiter );
boolean [effect] to_set_of_effect( string set );
string to_string( boolean [effect] set, string delimiter );
string to_string( boolean [effect] set );

boolean [familiar] to_set_of_familiar( string set, string delimiter );
boolean [familiar] to_set_of_familiar( string set );
string to_string( boolean [familiar] set, string delimiter );
string to_string( boolean [familiar] set );

boolean [monster] to_set_of_monster( string set, string delimiter );
boolean [monster] to_set_of_monster( string set );
string to_string( boolean [monster] set, string delimiter );
string to_string( boolean [monster] set );

boolean [element] to_set_of_element( string set, string delimiter );
boolean [element] to_set_of_element( string set );
string to_string( boolean [element] set, string delimiter );
string to_string( boolean [element] set );

boolean [phylum] to_set_of_phylum( string set, string delimiter );
boolean [phylum] to_set_of_phylum( string set );
string to_string( boolean [phylum] set, string delimiter );
string to_string( boolean [phylum] set );

boolean [coinmaster] to_set_of_coinmaster( string set, string delimiter );
boolean [coinmaster] to_set_of_coinmaster( string set );
string to_string( boolean [coinmaster] set, string delimiter );
string to_string( boolean [coinmaster] set );

boolean [thrall] to_set_of_thrall( string set, string delimiter );
boolean [thrall] to_set_of_thrall( string set );
string to_string( boolean [thrall] set, string delimiter );
string to_string( boolean [thrall] set );

boolean [bounty] to_set_of_bounty( string set, string delimiter );
boolean [bounty] to_set_of_bounty( string set );
string to_string( boolean [bounty] set, string delimiter );
string to_string( boolean [bounty] set );

boolean [servant] to_set_of_servant( string set, string delimiter );
boolean [servant] to_set_of_servant( string set );
string to_string( boolean [servant] set, string delimiter );
string to_string( boolean [servant] set );

boolean [vykea] to_set_of_vykea( string set, string delimiter );
boolean [vykea] to_set_of_vykea( string set );
string to_string( boolean [vykea] set, string delimiter );
string to_string( boolean [vykea] set );

// Lists:

boolean [int] to_list_of_boolean( string list, string delimiter );
boolean [int] to_list_of_boolean( string list );
string to_string( boolean [int] list, string delimiter );
string to_string( boolean [int] list );

int [int] to_list_of_int( string list, string delimiter );
int [int] to_list_of_int( string list );
string to_string( int [int] list, string delimiter );
string to_string( int [int] list );

float [int] to_list_of_float( string list, string delimiter );
float [int] to_list_of_float( string list );
string to_string( float [int] list, string delimiter );
string to_string( float [int] list );

string [int] to_list_of_string( string list, string delimiter );
string [int] to_list_of_string( string list );
string to_string( string [int] list, string delimiter );
string to_string( string [int] list );

item [int] to_list_of_item( string list, string delimiter );
item [int] to_list_of_item( string list );
string to_string( item [int] list, string delimiter );
string to_string( item [int] list );

location [int] to_list_of_location( string list, string delimiter );
location [int] to_list_of_location( string list );
string to_string( location [int] list, string delimiter );
string to_string( location [int] list );

class [int] to_list_of_class( string list, string delimiter );
class [int] to_list_of_class( string list );
string to_string( class [int] list, string delimiter );
string to_string( class [int] list );

stat [int] to_list_of_stat( string list, string delimiter );
stat [int] to_list_of_stat( string list );
string to_string( stat [int] list, string delimiter );
string to_string( stat [int] list );

skill [int] to_list_of_skill( string list, string delimiter );
skill [int] to_list_of_skill( string list );
string to_string( skill [int] list, string delimiter );
string to_string( skill [int] list );

effect [int] to_list_of_effect( string list, string delimiter );
effect [int] to_list_of_effect( string list );
string to_string( effect [int] list, string delimiter );
string to_string( effect [int] list );

familiar [int] to_list_of_familiar( string list, string delimiter );
familiar [int] to_list_of_familiar( string list );
string to_string( familiar [int] list, string delimiter );
string to_string( familiar [int] list );

monster [int] to_list_of_monster( string list, string delimiter );
monster [int] to_list_of_monster( string list );
string to_string( monster [int] list, string delimiter );
string to_string( monster [int] list );

element [int] to_list_of_element( string list, string delimiter );
element [int] to_list_of_element( string list );
string to_string( element [int] list, string delimiter );
string to_string( element [int] list );

phylum [int] to_list_of_phylum( string list, string delimiter );
phylum [int] to_list_of_phylum( string list );
string to_string( phylum [int] list, string delimiter );
string to_string( phylum [int] list );

coinmaster [int] to_list_of_coinmaster( string list, string delimiter );
coinmaster [int] to_list_of_coinmaster( string list );
string to_string( coinmaster [int] list, string delimiter );
string to_string( coinmaster [int] list );

thrall [int] to_list_of_thrall( string list, string delimiter );
thrall [int] to_list_of_thrall( string list );
string to_string( thrall [int] list, string delimiter );
string to_string( thrall [int] list );

bounty [int] to_list_of_bounty( string list, string delimiter );
bounty [int] to_list_of_bounty( string list );
string to_string( bounty [int] list, string delimiter );
string to_string( bounty [int] list );

servant [int] to_list_of_servant( string list, string delimiter );
servant [int] to_list_of_servant( string list );
string to_string( servant [int] list, string delimiter );
string to_string( servant [int] list );

vykea [int] to_list_of_vykea( string list, string delimiter );
vykea [int] to_list_of_vykea( string list );
string to_string( vykea [int] list, string delimiter );
string to_string( vykea [int] list );

// Values work best if they are "normalized".
//
// "seal tooth" is a normalized "item"
// "seal t" is not normalized.
// "snorkel|seal tooth" is a normalized "list" or "set" of "item"
// "snork|seal t" is not normalized
//
// This package provides functions to normalize string values. Since
// users can set properties to whatever they wish, it uses these
// functions itself, but user programs can also use them if they want to
// ensure that properties that they set are precise.

string normalize_value( string value, string type );

string normalize_list( string value, string type, string delimiter );
string normalize_list( string value, string type );
string normalize_set( string value, string type, string delimiter );
string normalize_set( string value, string type );

string normalize_value( string value, string type, string collection, string delimiter );
string normalize_value( string value, string type, string collection );

// define_property specifies that a particular property with NAME is of type TYPE.
// Optionally, you can declare that the value is a COLLECTION (either "list" or "set") with a DELIMITER
// NAME can be either built-in to KoLmafia or a custom user property.
// If it is a custom property, you can specify a DEFAULT value
//
// If the property exists, define_property will fetch the value,
// normalize it, and return it.
//    If the property is custom and the value is not normalized,
//    the property will be set with the normalized value.
//    If the property is custom and the normalized value equals
//    the normalized default value, the property will be removed.
//
// If the property does not exist, define_property will return the
// (normalized) default value and the property will remain unset.

string define_property( string name, string type, string def );
string define_property( string name, string type, string def, string collection );
string define_property( string name, string type, string def, string collection, string delimiter );

// You can use these in conjunction with the appropriate coercion
// function to extract the value of a property into the appropriate data
// type. For example:
//
// int prop1 = define_property( "prop1", "int", "12" ).to_int();
// boolean prop2 = define_property( "prop2", "boolean", "true" ).to_boolean();
// item prop3 = define_property( "prop3", "item", "snorkel" ).to_item();
// boolean [item] prop4 = define_property( "prop4", "item", "snorkel|seal tooth", "set" ).to_set_of_item();
// string [int] prop5 =  define_property( "prop5", "string", "str1,str2,str3", "list", "," ).to_list_of_string( "," );
 

Veracity

Developer
Staff member
This is coming along quickly. I have all the coercion functions and the normalization functions.

Code:
[color=green]> ash get_property( "_deckCardsSeen" )[/color]

Returned: 1952 Mickey Mantle|Ancestral Recall|Island

[color=green]> ash import <vprops.ash>; to_list_of_string( get_property( "_deckCardsSeen" ) )[/color]

Returned: aggregate string [int]
0 => 1952 Mickey Mantle
1 => Ancestral Recall
2 => Island

[color=green]> ash import <vprops.ash>; to_set_of_string( get_property( "_deckCardsSeen" ) )[/color]

Returned: aggregate boolean [string]
1952 Mickey Mantle => true
Ancestral Recall => true
Island => true

[color=green]> ash import <vprops.ash>; to_set_of_string( get_property( "_deckCardsSeen" ) ).to_string( "," )[/color]

Returned: 1952 Mickey Mantle,Ancestral Recall,Island
Not all of the coercion functions are especially useful; who will ever have a "set of booleans", for example? That one has exactly four possible values:

{}
{false}
{true}
{false,true}

But, for completeness, I allowed sets and lists of almost all of ASH's built-in data types.

Now that I think about it, I probably should make that "all", rather than "almost all". I skipped the following because they didn't seem useful:

coinmaster
thrall
bounty
servant
vykea

but you know, I could user a vykea property in my own script.

So I guess I will add them.
 

Veracity

Developer
Staff member
Code:
[color=green]> ash import <vprops.ash>; normalize_value( "snork|seal t", "item", "list" )[/color]

Returned: snorkel|none

[color=green]> ash import <vprops.ash>; to_string( item [int] { 1: $item[seal t] , 2 : $item[snork ] } )[/color]
[color=red]Bad item value: "seal t" ()[/color]
Returned: void

[color=green]> ash import <vprops.ash>; normalize_value( "snork|seal to", "item", "list" )[/color]

Returned: snorkel|seal tooth

[color=green]> ash import <vprops.ash>; normalize_value( "snork|seal to", "item", "set" )[/color]

Returned: seal tooth|snorkel

[color=green]> ash import <vprops.ash>; to_string( item [int] { 1: $item[seal to] , 2 : $item[snork ] } )[/color]

Changing "seal to" to "seal tooth" would get rid of this message. ()
Changing "snork" to "snorkel" would get rid of this message. ()
Returned: seal tooth|snorkel
normalize_value() calls to_item() to coerce strings to items.
I suppose it could generate its own "friendly warnings". Or not.
 

Veracity

Developer
Staff member
This script:

Code:
import <vprops.ash>;

int prop1 = define_property( "TVP.prop1", "int", "12" ).to_int();
print( "TVP.prop1 exists = " + property_exists( "TVP.prop1" ) );
print( "prop1 = " + prop1 );

set_property( "TVP.prop1", "10" );
prop1 = define_property( "TVP.prop1", "int", "12" ).to_int();
print( "TVP.prop1 exists = " + property_exists( "TVP.prop1" ) );
print( "prop1 = " + prop1 );

set_property( "TVP.prop1", "12" );
prop1 = define_property( "TVP.prop1", "int", "12" ).to_int();
print( "TVP.prop1 exists = " + property_exists( "TVP.prop1" ) );
print( "prop1 = " + prop1 );

print( "" );

boolean prop2 = define_property( "TVP.prop2", "boolean", "true" ).to_boolean();
print( "TVP.prop2 exists = " + property_exists( "TVP.prop2" ) );
print( "prop2 = " + prop2 );

print( "" );

item prop3 = define_property( "TVP.prop3", "item", "snorkel" ).to_item();
print( "TVP.prop3 exists = " + property_exists( "TVP.prop3" ) );
print( "prop3 = " + prop3 );

print( "" );

boolean [item] prop4 = define_property( "TVP.prop4", "item", "snorkel|seal tooth", "set" ).to_set_of_item();
print( "TVP.prop4 exists = " + property_exists( "TVP.prop4" ) );
print( "prop4 = " + prop4 );
foreach key, val in prop4 {
    print( key + " => " + val );
}

print( "" );

string [int] prop5 =  define_property( "TVP.prop5", "string", "str1,str2,str3", "list", "," ).to_list_of_string( "," );
print( "TVP.prop5 exists = " + property_exists( "TVP.prop5" ) );
print( "prop5 = " + prop5 );
foreach key, val in prop5 {
    print( key + " => " + val );
}

print( "" );

string [int] cards =  define_property( "_deckCardsSeen", "string", "str1,str2,str3", "list", "," ).to_list_of_string();
print( "_deckCardsSeen exists = " + property_exists( "_deckCardsSeen" ) );
print( "_deckCardsSeen = " + cards );
foreach key, val in cards {
    print( key + " => " + val );
}
Yields this:

Code:
[color=green]> test_vprops.ash[/color]

TVP.prop1 exists = false
prop1 = 12
TVP.prop1 => 10
TVP.prop1 exists = true
prop1 = 10
TVP.prop1 => 12
TVP.prop1 exists = false
prop1 = 12

TVP.prop2 exists = false
prop2 = true

TVP.prop3 exists = false
prop3 = snorkel

TVP.prop4 exists = false
prop4 = aggregate boolean [item]
seal tooth => true
snorkel => true

TVP.prop5 exists = false
prop5 = aggregate string [int]
0 => str1
1 => str2
2 => str3

_deckCardsSeen exists = true
_deckCardsSeen = aggregate string [int]
0 => 1952 Mickey Mantle
1 => Ancestral Recall
2 => Island
I'll release this into the wild.
 

Veracity

Developer
Staff member
Bale, if you want to add this to the catalog, perhaps this will do:

Code:
{
  "repo": "https://svn.code.sf.net/p/veracity0/code/vprops/", 
  "author": "Veracity", 
  "name": "Veracity's Property Management Library", 
  "forumThread": "http://kolmafia.us/showthread.php?21593", 
  "shortDesc": "Functions to easily manage custom properties", 
  "category": "library", 
  "longDesc": "Functions to manage custom properties and convert back and forth between simple data types (and sets and lists of such) and a string representation which is suitable to store in such properties."
 }
I guessed about the "category".
 

Bale

Minion
I decided it was appropriate to make a few changes:

Code:
 {
  "repo": "https://svn.code.sf.net/p/veracity0/code/vprops/", 
  "author": "Veracity", 
  "name": "vProps", 
  "forumThread": "http://kolmafia.us/showthread.php?21593-Veracity-s-Property-Management-Library-vprops-ash", 
  "shortDesc": "Veracity's property management library", 
  "category": "library", 
  "longDesc": "Functions to easily manage custom properties and convert back and forth between simple data types (and sets and lists of such) and a string representation which is suitable to store in such properties.<p style='text-align:center;font-style:italic'>This library script will not work by itself and may be automatically installed by other scripts.</p>"
 },

I don't like names to be much longer than the default field size. Plus I use a default disclaimer for all library scripts.
 

Bale

Minion
I'd like to share something.

Code:
string normalize_value( string value, string type )
{
	if( $strings[boolean,int,float,item,location,class,stat,skill,effect,familiar,monster,element,phylum,coinmaster,thrall,bounty,servant,vykea] contains type )
	{
		string prog = "to_" + type;
		return call string prog( value );
	}
	// If type is "string", or invalid, don't convert anything
	return value;
}

I don't suppose anyone can imagine a way to check if something is a valid data type without hard-coding a list of them?
 
Last edited:

Bale

Minion
I've just moved this script from "Scripting Discussion" to "Informational Scripts" because it was created in a forum that isn't intended for discussing and supporting an active published script.
 

Veracity

Developer
Staff member
I want to let you know that I am aware of your "few changes".

I was at a job interview all day and am still psyched about it, so am not thinking deeply about this - but I will. Wish me luck!

I don't, personally, like "call". Yes, I added it to ASH, and I see that it can shorten code, but, contrary to what you might think, I am not convinced it is more "efficient", since it pushes the method lookup from compile-time to run-time.

I'll comment more later, but I'll say now: it is not a no-brainer (for me) to adopt your change.

But I greatly appreciate your looking at my code and considering adopting (parts of) it!
 

Bale

Minion
I really love this, but I want to make a request of all scripters who use this library to store their preferences in mafia's pref files.

Always make sure that the properties you create BEGIN with information to identify the script which created them. This will help a lot once a lot of script have made use use of Veracity's new concept in script configuration. I know I will be using it.
 
One of the things zlib includes that I find immensely useful, and is a big reason why I use its vars, is the WOSSMAN relay script for easy management. I've mangled Zarqon's script to make a version that manages preferences instead. To do this I had to also make a library script (I called it "vprops2") that keeps track of property types and stores them in a data file, "PropertyTypes.txt". The first time it's run it gets a list of all properties and attempts to guess their types, but they can be changed as needed in the relay script.

I put vprops2 up here, and the prefs relay is here. Again, that relay is clearly just a mod of WOSSMAN, so all credit to Zarqon. If you find vprops2 usefull feel free to incorporate however much of it you want into vprops or whatever else you want.

At the top of the PREFS relay is the option "PREFS_showbuiltin". If you turn this on and then refresh, the relay will no longer display custom props, but will show all builtin ones instead.

One thing I've realized is that the builtin properties kind of come in two varieties with no obvious way to differentiate - they're either managed & updated by Mafia (things like quest status values, numbers of times various things have been used/dropped, etc), or they can be preferences the user might want to change, like the various scripts you might have assigned or other preferences.

I wanted to first make sure there isn't a way to tell them apart already, and if there isn't, what you think the best way might be? I don't think there's any getting around the fact that it'd require going through all the builtin properties and labeling them as one or the other. I could conceivably just curate all the readonly properties and dump the set to another data file, or add a property in PropertyTypes... hmm.

edit: Derp, there's of course also the fact that any non-builtin properties that aren't changed from default couldn't be found this way. There'd have to be a separate list of those somewhere.
 
Last edited:
Okay, here's what I've done:

vprops2 imports vprops, but doesn't automatically load the types map. It includes define_property2, which first takes the scriptname as the first argument, then the rest of the values same as define_property. If you use define_property2 to define your property, it stores the type data in PropertyTypes.txt and remembers that property name in another property named PREFS_known_<scriptname>. It only bothers to load the types map in the future if it doesn't see the property in that list. This, I think, preserves the intent of vprops while also allowing a settings script to see what settings are available and what their types should be. One additional benefit of this is a normalize_property function that doesn't require the type, since the map already has it.

The first time vprops2 is run, it runs through the user properties list and attempts to guess at both their datatypes and 'readonly' status based on the data and property name. These can then be changed individually in the PREFS interface.

I think I've gone about as far as I can go with it, I hope other people find it as necessary as I do.

vprops2: https://sourceforge.net/p/kolm-prefs/svn/HEAD/tree/scripts/vprops2.ash
relay_PREFS: https://sourceforge.net/p/kolm-prefs/svn/HEAD/tree/relay/relay_PREFS.ash
 
Last edited:

Veracity

Developer
Staff member
OK, I need to look closely at what you've done here. When I saw your post, I was on my way out the door, so I deferred comment until later - and it dropped off my "new posts". You've done a lot of work and deserve a response. Which I will give you. Soonish. ;)

I came to report that I submitted a bug fix. Turns out that using split_string() to separate a property into elements for a set or a list has a flaw: that function ALWAYS gives at least one string: if there is no delimiter, you get back the original string. Which is fine - except when the original string is "", where this library wants/expects/needs to end up with an empty set or list.

Revision 29 makes that so: to_list_of_xxx( "" ) will now give you a list with 0 elements in it. Ditto for sets.

(And it is revision 29 not because I have been busy as a bee changing this library. All three of my scripts on sourceforge are in subdirectories of the same repository, so a change to any will bump the latest version for all. I've been busy as a bee with my other scripts.)
 

Veracity

Developer
Staff member
(Still need to comment on vprops2, etc. I will say that when I was first thinking about this, I was expecting that define_property() woud store info in a local database - sort of like what vlib does - but only the meta-information about the property; you'd still edit the property via "set" in the gCLI. I decided that was unnecessary for what _I_ needed, so I didn't go there. For, you, however, it is "essential", so you went there. Pondering.)

I have a standard header that I include in my (four, currently) scripts that use this to try and make it clear what the script user can do: edit the file, or, (preferred), simply "set" the properties. It's become clear that my "simple and obvious" instructions are neither. Here is what I say. Suggestions for improved script boilerplate is welcome.

Code:
//-------------------------------------------------------------------------
// All of the configuration variables have default values, which apply
// to any character who does not override the variable using the
// appropriate property.
//
// You can edit the default here in the script and it will apply to all
// characters which do not override it.
//
// define_property( PROPERTY, TYPE, DEFAULT )
// define_property( PROPERTY, TYPE, DEFAULT, COLLECTION )
// define_property( PROPERTY, TYPE, DEFAULT, COLLECTION, DELIMITER )
//
// Otherwise, you can change the value for specific characters in the gCLI:
//
//     set PROPERTY=VALUE
//
// Both DEFAULT and a property VALUE will be normalized
//
// All properties used directly by this script start with "VGC."
//-------------------------------------------------------------------------
Obviously, that last line is not "boilerplate", but is specific to the particular script that includes the rest of the comment.
 

fronobulax

Developer
Staff member
For some reason it seems counter-intuitive to me to open up a script in a text viewer/editor to view the properties that are available to me and then go somewhere else (command line, property setting script) to choose/specify my changes/preferences for that property. There is no reason for that other than personal preference, but the relay script to view and set the parameters for bccascend remains my preferred way to view and set those parameters. Similarly there is a very old script that displays zlib parameters and allows them to be edited. That provides no documentation but it does allow the values to be set.

So as a user I'd love a relay script because then I can see what all the properties are, (potentially) set them to valid values without worrying about typos or exact spelling and have some kind of documentation. I can even imagine a script with a validate button on it so I could validate input/changes when I was in a place that supported fixing errors. A Restore defaults button would also be useful.

As someone who sees everything as a potential problem to be fixed and tends to seize the first solution, I can imagine code that reads a file and dynamically builds such a relay script. The data file can be a dependency for scripts that use SVN. I'd consider making the relay builder a Kolmafia function and figure out a means whereby the user could trigger a build/rebuild.

Reworking my scripts to use the new property scheme is on my TODO list and if by converting, I get a relay script setter for free I am even more inspired to convert. That said, my KoLmafia TODO list never seems to get the attention it deserves. I want to blame my position as the volunteer IT department for a small non-profit that was compromised and needs computers cleaned up and secured but I am sure Fallout 4 gets some of the blame ;-)
 

Veracity

Developer
Staff member
I have a major - and not backwards-compatible - update to this. Revision 275 does this:

- Adds "slot", which was the only basic ASH data type it didn't support. Weird.
- provides typedefs for all the "set" and "list" types:

Code:
typedef boolean [boolean] boolean_set;
typedef boolean [int] int_set;
typedef boolean [float] float_set;
typedef boolean [string] string_set;
typedef boolean [item] item_set;
typedef boolean [location] location_set;
typedef boolean [class] class_set;
typedef boolean [stat] stat_set;
typedef boolean [skill] skill_set;
typedef boolean [effect] effect_set;
typedef boolean [familiar] familiar_set;
typedef boolean [slot] slot_set;
typedef boolean [monster] monster_set;
typedef boolean [element] element_set;
typedef boolean [phylum] phylum_set;
typedef boolean [coinmaster] coinmaster_set;
typedef boolean [thrall] thrall_set;
typedef boolean [bounty] bounty_set;
typedef boolean [servant] servant_set;
typedef boolean [vykea] vykea_set;

typedef boolean [int] boolean_list;
typedef int [int] int_list;
typedef float [int] float_list;
typedef string [int] string_list;
typedef item [int] item_list;
typedef location [int] location_list;
typedef class [int] class_list;
typedef stat [int] stat_list;
typedef skill [int] skill_list;
typedef effect [int] effect_list;
typedef familiar [int] familiar_list;
typedef slot [int] slot_list;
typedef monster [int] monster_list;
typedef element [int] element_list;
typedef phylum [int] phylum_list;
typedef coinmaster [int] coinmaster_list;
typedef thrall [int] thrall_list;
typedef bounty [int] bounty_list;
typedef servant [int] servant_list;
typedef vykea [int] vykea_list;
- Provides coercion functions to and from strings for all 20 set types and alll 20 list types.
- And the non-compatible change is that they are now named suitably for ASH's new automatic coercion feature to be able to find them:

We used to have "string_set to_set_of_string( string val )"
We now have "string_set to_string_set( string val )".

Interestingly, when I did that, it revealed a bug in KoLmafia, which I fixed in revision 20079. Hence, there is a "since" directive in vprops for that revision.

All of my other published scripts use vprops. I updated them all to conform and revision 275 updates them as well; "svn update" will bring in the updated versions of any of my scripts that you installed.
 

Veracity

Developer
Staff member
Today I migrated this from sourceforge using SVN to github using GIT.
Future updates (such as adding the "path" datatype) will be pushed only to the latter.

I suggest you delete the SVN version (make sure you have KoLmafia r27304!) and then install it via GIT:

Code:
git checkout Veracity0/vprops
 
Top