Renamed inc_array to stop nwnx include collisions Added missing bonus feat 2da for Forest Master. Changed prc_newspellbook.hak to prc_nsb.hak to prevent issues with nwserver. Updated tester module. Updated release archive.
668 lines
20 KiB
Plaintext
668 lines
20 KiB
Plaintext
//::///////////////////////////////////////////////
|
|
//:: Set-like storage data type include
|
|
//:: inc_set
|
|
//:://////////////////////////////////////////////
|
|
/** @file
|
|
This file defines a "data type" that behaves
|
|
like a set. It is implemented as an extension
|
|
of the arrays defined in prc_inc_array.
|
|
|
|
Operations:
|
|
- Get number of entities in the set. O(1)
|
|
- Store an entity in the set. O(1)
|
|
- Remove an entity from the set. O(n)
|
|
- Determine if the set contains a given entity. O(1)
|
|
- Get operations on the underlying array
|
|
|
|
The memory complexity is O(n), specifically 2n(m + c), where
|
|
n is the number of entities stored in the set, m is the memory
|
|
taken up the local variable store of a member entity and c is
|
|
a constant overhead from disambiguation strings.
|
|
|
|
Note that a set can contain only contain one instance
|
|
of any specific entity. Any attempts to add an entity to
|
|
a set that is already a member of will return with success,
|
|
but do nothing.
|
|
For example, if a set contains {"Foo", "Bar, 123, OBJECT_INVALID}
|
|
calling set_add_string(container, setname, "Foo") will return
|
|
SDL_SUCCESS, but not modify the contents of the set.
|
|
|
|
|
|
@author Ornedan
|
|
@date Created - 2006.09.16
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:://////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function prototypes */
|
|
//////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Creates a new set on the given storage object. If a set with
|
|
* the same name already exists, the function fails.
|
|
*
|
|
* @param store The object to use as holder for the set
|
|
* @param name The name of the set
|
|
* @return SDL_SUCCESS if the set was successfully created,
|
|
* one of SDL_ERROR_* on error.
|
|
*/
|
|
int set_create(object store, string name);
|
|
|
|
/**
|
|
* Deletes a set, deleting all local variables it consists of.
|
|
*
|
|
* @param store The object which holds the set to delete
|
|
* @param name The name of the set
|
|
* @return SDL_SUCCESS if the set was successfully deleted,
|
|
* one of SDL_ERROR_* on error
|
|
*/
|
|
int set_delete(object store, string name);
|
|
|
|
/**
|
|
* Adds a string to the set.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entry The string to add
|
|
* @return SDL_SUCCESS if the addition was successfull, SDL_ERROR_* on error.
|
|
*/
|
|
int set_add_string(object store, string name, string entry);
|
|
|
|
/**
|
|
* Adds a integer to the set.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entry The integer to add
|
|
* @return SDL_SUCCESS if the addition was successfull, SDL_ERROR_* on error.
|
|
*/
|
|
int set_add_int(object store, string name, int entry);
|
|
|
|
/**
|
|
* Adds a float to the set.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entry The float to add
|
|
* @return SDL_SUCCESS if the addition was successfull, SDL_ERROR_* on error.
|
|
*/
|
|
int set_add_float(object store, string name, float entry);
|
|
|
|
/**
|
|
* Adds a object to the set.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entry The object to add
|
|
* @return SDL_SUCCESS if the addition was successfull, SDL_ERROR_* on error.
|
|
*/
|
|
int set_add_object(object store, string name, object entry);
|
|
|
|
/**
|
|
* Determines whether the set contains the given string.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The string to test
|
|
* @return TRUE if the set contains entry, FALSE otherwise
|
|
*/
|
|
int set_contains_string(object store, string name, string entity);
|
|
|
|
/**
|
|
* Determines whether the set contains the given integer.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The integer to test
|
|
* @return TRUE if the set contains entry, FALSE otherwise
|
|
*/
|
|
int set_contains_int(object store, string name, int entity);
|
|
|
|
/**
|
|
* Determines whether the set contains the given float.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The float to test
|
|
* @return TRUE if the set contains entry, FALSE otherwise
|
|
*/
|
|
int set_contains_float(object store, string name, float entity);
|
|
|
|
/**
|
|
* Determines whether the set contains the given object.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The object to test
|
|
* @return TRUE if the set contains entry, FALSE otherwise
|
|
*/
|
|
int set_contains_object(object store, string name, object entity);
|
|
|
|
/**
|
|
* Removes the given string from the set, if it is a member.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The string to remove
|
|
*/
|
|
void set_remove_string(object store, string name, string entity);
|
|
|
|
/**
|
|
* Removes the given integer from the set, if it is a member.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The integer to remove
|
|
*/
|
|
void set_remove_int(object store, string name, int entity);
|
|
|
|
/**
|
|
* Removes the given float from the set, if it is a member.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The float to remove
|
|
*/
|
|
void set_remove_float(object store, string name, float entity);
|
|
|
|
/**
|
|
* Removes the given object from the set, if it is a member.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The object to remove
|
|
*/
|
|
void set_remove_object(object store, string name, object entity);
|
|
|
|
/**
|
|
* Gets the type of the i:th member of the set.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param i The index of the member the type of which to retrieve
|
|
* @return One of the ENTITY_TYPE_* defined in inc_heap, or 0 in case of error
|
|
*/
|
|
int set_get_member_type(object store, string name, int i);
|
|
|
|
|
|
/**
|
|
* Gets the i:th member of the set as a string.
|
|
*
|
|
* NOTE: If the member is actually not a string, the return
|
|
* value in undefined. As such, always check the real
|
|
* type of the member first using set_get_member_type().
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param i The index to retrieve the string from
|
|
* @return The value contained at the index on success,
|
|
* "" on error
|
|
*/
|
|
string set_get_string(object store, string name, int i);
|
|
|
|
/**
|
|
* Gets the i:th member of the set as an integer.
|
|
*
|
|
* NOTE: If the member is actually not an integer, the return
|
|
* value in undefined. As such, always check the real
|
|
* type of the member first using set_get_member_type().
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param i The index to retrieve the string from
|
|
* @return The value contained at the index on success,
|
|
* 0 on error
|
|
*/
|
|
int set_get_int(object store, string name, int i);
|
|
|
|
/**
|
|
* Gets the i:th member of the set as an float.
|
|
*
|
|
* NOTE: If the member is actually not an float, the return
|
|
* value in undefined. As such, always check the real
|
|
* type of the member first using set_get_member_type().
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param i The index to retrieve the string from
|
|
* @return The value contained at the index on success,
|
|
* 0.0 on error
|
|
*/
|
|
float set_get_float(object store, string name, int i);
|
|
|
|
/**
|
|
* Gets the i:th member of the set as an object.
|
|
*
|
|
* NOTE: If the member is actually not an object, the return
|
|
* value in undefined. As such, always check the real
|
|
* type of the member first using set_get_member_type().
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param i The index to retrieve the string from
|
|
* @return The value contained at the index on success,
|
|
* OBJECT_INVALID on error
|
|
*/
|
|
object set_get_object(object store, string name, int i);
|
|
|
|
/**
|
|
* Gets the number of members in the set
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @return The size of the set, or -1 if the specified
|
|
* set does not exist.
|
|
*/
|
|
int set_get_size(object store, string name);
|
|
|
|
/**
|
|
* Checks whether the given set exists.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @return TRUE if the set exists, FALSE otherwise.
|
|
*/
|
|
int set_exists(object store, string name);
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Includes */
|
|
//////////////////////////////////////////////////
|
|
|
|
// prc_inc_array access is via inc_heap
|
|
//#include "prc_inc_array"
|
|
#include "inc_debug"
|
|
#include "inc_heap"
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Internal Constants */
|
|
//////////////////////////////////////////////////
|
|
|
|
const string _PRC_SET_PREFIX = "@@@set";
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Internal functions */
|
|
//////////////////////////////////////////////////
|
|
|
|
/** Internal function.
|
|
* Performs the real addition operation.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entry String form of the entity to be stored in the set
|
|
* @param isobject Whether the entity being stored is an object. Objects need special handling
|
|
* @param obj The object being stored, if any
|
|
*/
|
|
int _inc_set_set_add_aux(object store, string name, string entry, int isobject = FALSE, object obj = OBJECT_INVALID)
|
|
{
|
|
// Sanity checks
|
|
if(!set_exists(store, name))
|
|
return SDL_ERROR_DOES_NOT_EXIST;
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
// Set the presence marker to be the index where the entity will be stored + 1 to avoid storing a 0
|
|
int index = array_get_size(store, name);
|
|
SetLocalInt(store, name + entry, index + 1);
|
|
|
|
// Store the member's value in the array
|
|
if(isobject)
|
|
{
|
|
if(DEBUG)
|
|
{
|
|
Assert(array_set_object(store, name, index, obj) == SDL_SUCCESS,
|
|
"array_set_object(store, name, index, obj) == SDL_SUCCESS",
|
|
"", "inc_set", "_inc_set_set_add_aux"
|
|
);
|
|
return SDL_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return array_set_object(store, name, index, obj);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(DEBUG)
|
|
{
|
|
Assert(array_set_string(store, name, index, entry) == SDL_SUCCESS,
|
|
"array_set_string(store, name, index, entry) == SDL_SUCCESS",
|
|
"", "inc_set", "_inc_set_set_add_aux"
|
|
);
|
|
return SDL_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return array_set_string(store, name, index, entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Internal function.
|
|
* Determines whether the set contains the given entity.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The presence string for the entity to test
|
|
* @return TRUE if the set contains the entity, FALSE otherwise
|
|
*/
|
|
int _inc_set_set_contains_aux(object store, string name, string entity)
|
|
{
|
|
// Sanity check
|
|
if(!set_exists(store, name))
|
|
return FALSE;
|
|
|
|
// Get the value of the presence marker and normalise to TRUE / FALSE
|
|
return GetLocalInt(store, _PRC_SET_PREFIX + name + entity) != 0;
|
|
}
|
|
|
|
/** Internal function.
|
|
* Removes the given entity from the set.
|
|
*
|
|
* @param store The object holding the set
|
|
* @param name The name of the set
|
|
* @param entity The presence string for the entity to remove
|
|
*/
|
|
void _inc_set_set_remove_aux(object store, string name, string entity)
|
|
{
|
|
// Set does not exist or exists, but does not contain the given entity. Nothing to do
|
|
if(!_inc_set_set_contains_aux(store, name, entity))
|
|
return;
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
// Get the index where the entity is stored and the size of the underlying array
|
|
int index = GetLocalInt(store, name + entity) - 1;
|
|
int size = array_get_size(store, name);
|
|
string raw;
|
|
object obj;
|
|
|
|
// Move each element in the array after the one being removed back by one
|
|
for(index = index + 1; index < size; index++)
|
|
{
|
|
// Determine what's stored here
|
|
raw = array_get_string(store, name, index);
|
|
|
|
// Different handling for objects vs everything else
|
|
if(raw == "OBJECT")
|
|
{
|
|
obj = array_get_object(store, name, index);
|
|
// Move back
|
|
array_set_object(store, name, index - 1, obj);
|
|
|
|
// Update the marker value
|
|
SetLocalInt(store, name + "O" + ObjectToString(obj), index/* - 1 + 1 */);
|
|
}
|
|
else
|
|
{
|
|
// Move back
|
|
array_set_string(store, name, index - 1, raw);
|
|
|
|
// Update the marker value
|
|
SetLocalInt(store, name + raw, index/* - 1 + 1 */);
|
|
}
|
|
}
|
|
|
|
// Delete the marker local
|
|
DeleteLocalInt(store, name + entity);
|
|
|
|
// Shrink the array
|
|
array_shrink(store, name, size - 1);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function definitions */
|
|
//////////////////////////////////////////////////
|
|
|
|
int set_create(object store, string name)
|
|
{
|
|
// Sanity checks
|
|
if(!GetIsObjectValid(store))
|
|
return SDL_ERROR_NOT_VALID_OBJECT;
|
|
if(name == "")
|
|
return SDL_ERROR_INVALID_PARAMETER;
|
|
if(set_exists(store, name))
|
|
return SDL_ERROR_ALREADY_EXISTS;
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
// All OK, create the underlying array
|
|
return array_create(store, name);
|
|
}
|
|
|
|
int set_delete(object store, string name)
|
|
{
|
|
// Sanity check
|
|
if(!set_exists(store, name))
|
|
return SDL_ERROR_DOES_NOT_EXIST;
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
// Loop over all members, getting deleting the presence indicator local
|
|
int size = array_get_size(store, name);
|
|
int i;
|
|
string raw, member;
|
|
for(i = 0; i < size; i++)
|
|
{
|
|
// Get the raw data stored in the array.
|
|
// NOTE: This relies on internal details of the array implementation. Specifically, objects having a string containing "OBJECT"
|
|
// stored in their position
|
|
raw = array_get_string(store, name, i);
|
|
|
|
// Construct the presence marker name. Special handling for objects
|
|
if(raw == "OBJECT")
|
|
member = name + "O" + ObjectToString(array_get_object(store, name, i));
|
|
else
|
|
member = name + raw;
|
|
|
|
// Delete the marker
|
|
DeleteLocalInt(store, member);
|
|
}
|
|
|
|
// Clean up the underlying array
|
|
if(DEBUG)
|
|
{
|
|
Assert(array_delete(store, name) == SDL_SUCCESS, "array_delete(store, name) == SDL_SUCCESS", "", "inc_set", "set_delete");
|
|
return SDL_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return array_delete(store, name);
|
|
}
|
|
}
|
|
|
|
int set_add_string(object store, string name, string entry)
|
|
{
|
|
// Convert the entry to the storable string form
|
|
entry = "S" + entry;
|
|
|
|
// If the set already contains the entry being added, nothing happens
|
|
if(_inc_set_set_contains_aux(store, name, entry))
|
|
return SDL_SUCCESS;
|
|
|
|
return _inc_set_set_add_aux(store, name, entry);
|
|
}
|
|
|
|
int set_add_int(object store, string name, int entry)
|
|
{
|
|
// Convert the entry to the storable string form
|
|
string strentry = "I" + IntToString(entry);
|
|
|
|
// If the set already contains the entry being added, nothing happens
|
|
if(_inc_set_set_contains_aux(store, name, strentry))
|
|
return SDL_SUCCESS;
|
|
|
|
return _inc_set_set_add_aux(store, name, strentry);
|
|
}
|
|
|
|
int set_add_float(object store, string name, float entry)
|
|
{
|
|
// Convert the entry to the storable string form
|
|
string strentry = "F" + FloatToString(entry);
|
|
|
|
// If the set already contains the entry being added, nothing happens
|
|
if(_inc_set_set_contains_aux(store, name, strentry))
|
|
return SDL_SUCCESS;
|
|
|
|
return _inc_set_set_add_aux(store, name, strentry);
|
|
}
|
|
|
|
int set_add_object(object store, string name, object entry)
|
|
{
|
|
// Convert the entry to the storable string form
|
|
string strentry = "O" + ObjectToString(entry);
|
|
|
|
// If the set already contains the entry being added, nothing happens
|
|
if(_inc_set_set_contains_aux(store, name, strentry))
|
|
return SDL_SUCCESS;
|
|
|
|
return _inc_set_set_add_aux(store, name, strentry, TRUE, entry);
|
|
}
|
|
|
|
int set_get_member_type(object store, string name, int i)
|
|
{
|
|
// Sanity check
|
|
if(!set_exists(store, name) || i >= set_get_size(store, name))
|
|
return 0;
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
// Grab the first character of the raw string, it determines type
|
|
string type = GetSubString(array_get_string(store, name, i), 0, 1);
|
|
|
|
// First character in the string determines type
|
|
if (type == "F")
|
|
return ENTITY_TYPE_FLOAT;
|
|
else if(type == "I")
|
|
return ENTITY_TYPE_INTEGER;
|
|
else if(type == "O")
|
|
return ENTITY_TYPE_OBJECT;
|
|
else if(type == "S")
|
|
return ENTITY_TYPE_STRING;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int set_contains_string(object store, string name, string entity)
|
|
{
|
|
return _inc_set_set_contains_aux(store, name, "S" + entity);
|
|
}
|
|
|
|
int set_contains_int(object store, string name, int entity)
|
|
{
|
|
return _inc_set_set_contains_aux(store, name, "I" + IntToString(entity));
|
|
}
|
|
|
|
int set_contains_float(object store, string name, float entity)
|
|
{
|
|
return _inc_set_set_contains_aux(store, name, "F" + FloatToString(entity));
|
|
}
|
|
|
|
int set_contains_object(object store, string name, object entity)
|
|
{
|
|
return _inc_set_set_contains_aux(store, name, "O" + ObjectToString(entity));
|
|
}
|
|
|
|
void set_remove_string(object store, string name, string entity)
|
|
{
|
|
_inc_set_set_remove_aux(store, name, "S" + entity);
|
|
}
|
|
|
|
void set_remove_int(object store, string name, int entity)
|
|
{
|
|
_inc_set_set_remove_aux(store, name, "I" + IntToString(entity));
|
|
}
|
|
|
|
void set_remove_float(object store, string name, float entity)
|
|
{
|
|
_inc_set_set_remove_aux(store, name, "F" + FloatToString(entity));
|
|
}
|
|
|
|
void set_remove_object(object store, string name, object entity)
|
|
{
|
|
_inc_set_set_remove_aux(store, name, "O" + ObjectToString(entity));
|
|
}
|
|
|
|
string set_get_string(object store, string name, int i)
|
|
{
|
|
// Sanity check
|
|
if(!set_exists(store, name) || i >= set_get_size(store, name))
|
|
return "";
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
// Chop off the first character from the raw string and return the rest
|
|
string raw = array_get_string(store, name, i);
|
|
return GetSubString(raw, 1, GetStringLength(raw));
|
|
}
|
|
|
|
int set_get_int(object store, string name, int i)
|
|
{
|
|
// Sanity check
|
|
if(!set_exists(store, name) || i >= set_get_size(store, name))
|
|
return 0;
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
// Chop off the first character from the raw string and return the rest
|
|
string raw = array_get_string(store, name, i);
|
|
return StringToInt(GetSubString(raw, 1, GetStringLength(raw)));
|
|
}
|
|
|
|
float set_get_float(object store, string name, int i)
|
|
{
|
|
// Sanity check
|
|
if(!set_exists(store, name) || i >= set_get_size(store, name))
|
|
return 0.0f;
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
// Chop off the first character from the raw string and return the rest
|
|
string raw = array_get_string(store, name, i);
|
|
return StringToFloat(GetSubString(raw, 1, GetStringLength(raw)));
|
|
}
|
|
|
|
object set_get_object(object store, string name, int i)
|
|
{
|
|
// Sanity check
|
|
if(!set_exists(store, name) || i >= set_get_size(store, name))
|
|
return OBJECT_INVALID;
|
|
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
return array_get_object(store, name, i);
|
|
}
|
|
|
|
int set_get_size(object store, string name)
|
|
{
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
return array_get_size(store, name);
|
|
}
|
|
|
|
int set_exists(object store, string name)
|
|
{
|
|
// Generate real name for accessing array functions
|
|
name = _PRC_SET_PREFIX + name;
|
|
|
|
return array_exists(store, name);
|
|
}
|
|
|
|
|
|
// Test main
|
|
//void main() {}
|