// +====================================================+
// }                                                    |
// | NWScript Array API                                 |
// | Version 1.1                                        |
// |                                                    |
// | by Evan Machusak                                   |
// |                                                    |
// | Comments?  Suggestions?                            |
// | @#NWNScript, irc.stratics.com                      |
// | emachusa@wam.umd.edu                               |
// |                                                    |
// | Thanks to Speeder, j_dunn, and Sikarian for        |
// | assistance in testing, suggestions, & support      |
// |                                                    |
// | http://www.draconianempire.com/nwn                 |
// |                                                    |
// | 26 June 2002                                       |
// +====================================================+

// -------------------------------------------------------------------
// ---------------------------------------------------------------
// ******************************************************
// FUNCTION PROTOTYPES
// ******************************************************

// common functions
    int GetArraySize(string sName, object oTarget = OBJECT_SELF);
    location DefaultLocation();
    int GetIsArrayIndexValid(string sName, int nIndex, object oTarget = OBJECT_SELF);

// integer arrays
    int GetIntArraySize(string sName, object oTarget = OBJECT_SELF);
    void SetIntArray(string sName, int nIndex, int nValue, object oTarget = OBJECT_SELF);
    int GetIntArray(string sName, int nIndex, object oTarget = OBJECT_SELF);
    void CreateIntArray(string sName, int nSize, int nDefault = 0, object oTarget = OBJECT_SELF);
    void ClearIntArray(string sName, int nDefault = 0, object oTarget = OBJECT_SELF);
    void DeleteIntArray(string sName, object oTarget = OBJECT_SELF);
    int SearchIntArray(string sName, int nValue, object oTarget = OBJECT_SELF);
    int ResizeIntArray(string sName, int nSize, int nDefault = 0, object oTarget = OBJECT_SELF);
    void CopyIntArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF);
    void AppendIntArray(string sName, int nValue, object oTarget = OBJECT_SELF);
    void RemoveIntArray(string sName, int index, object oTarget = OBJECT_SELF);
    void PrintIntArray(string sName, object oTarget = OBJECT_SELF);

// floating point arrays
    int GetFloatArraySize(string sName, object oTarget = OBJECT_SELF);
    void SetFloatArray(string sName, int nIndex, float fValue, object oTarget = OBJECT_SELF);
    float GetFloatArray(string sName, int nIndex, object oTarget = OBJECT_SELF);
    void CreateFloatArray(string sName, int nSize, float fDefault = 0.0, object oTarget = OBJECT_SELF);
    void ClearFloatArray(string sName, float fDefault = 0.0, object oTarget = OBJECT_SELF);
    void DeleteFloatArray(string sName, object oTarget = OBJECT_SELF);
    int SearchFloatArray(string sName, float fValue, object oTarget = OBJECT_SELF);
    int ResizeFloatArray(string sName, int nSize, float fDefault = 0.0, object oTarget = OBJECT_SELF);
    void CopyFloatArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF);
    void AppendFloatArray(string sName, float fValue, object oTarget = OBJECT_SELF);
    void RemoveFloatArray(string sName, int index, object oTarget = OBJECT_SELF);
    void PrintFloatArray(string sName, object oTarget = OBJECT_SELF);

// string arrays
    int GetStringArraySize(string sName, object oTarget = OBJECT_SELF);
    void SetStringArray(string sName, int nIndex, string sValue, object oTarget = OBJECT_SELF);
    string GetStringArray(string sName, int nIndex, object oTarget = OBJECT_SELF);
    void CreateStringArray(string sName, int nSize, string sDefault = "", object oTarget = OBJECT_SELF);
    void ClearStringArray(string sName, string sDefault = "", object oTarget = OBJECT_SELF);
    void DeleteStringArray(string sName, object oTarget = OBJECT_SELF);
    int SearchStringArray(string sName, string sValue, object oTarget = OBJECT_SELF);
    int ResizeStringArray(string sName, int nSize, string sDefault = "", object oTarget = OBJECT_SELF);
    void CopyStringArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF);
    void AppendStringArray(string sName, string sValue, object oTarget = OBJECT_SELF);
    void RemoveStringArray(string sName, int index, object oTarget = OBJECT_SELF);
    void PrintStringArray(string sName, object oTarget = OBJECT_SELF);

// object arrays
    int GetObjectArraySize(string sName, object oTarget = OBJECT_SELF);
    void SetObjectArray(string sName, int nIndex, object oValue, object oTarget = OBJECT_SELF);
    object GetObjectArray(string sName, int nIndex, object oTarget = OBJECT_SELF);
    void CreateObjectArray(string sName, int nSize, object oDefault = OBJECT_INVALID, object oTarget = OBJECT_SELF);
    void ClearObjectArray(string sName, object oDefault = OBJECT_INVALID, object oTarget = OBJECT_SELF);
    void DeleteObjectArray(string sName, object oTarget = OBJECT_SELF);
    int SearchObjectArray(string sName, object oValue, object oTarget = OBJECT_SELF);
    int ResizeObjectArray(string sName, int nSize, object oDefault = OBJECT_INVALID, object oTarget = OBJECT_SELF);
    void CopyObjectArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF);
    void AppendObjectArray(string sName, object oValue, object oTarget = OBJECT_SELF);
    void RemoveObjectArray(string sName, int index, object oTarget = OBJECT_SELF);
    void PrintObjectArray(string sName, object oTarget = OBJECT_SELF);

// location arrays
    int GetLocationArraySize(string sName, object oTarget = OBJECT_SELF);
    void SetLocationArray(string sName, int nIndex, location lValue, object oTarget = OBJECT_SELF);
    location GetLocationArray(string sName, int nIndex, object oTarget = OBJECT_SELF);
    void CreateLocationArray(string sName, int nSize, location lDefault, object oTarget = OBJECT_SELF);
    void DeleteLocationArray(string sName, object oTarget = OBJECT_SELF);
    int SearchLocationArray(string sName, location lValue, object oTarget = OBJECT_SELF);
    int ResizeLocationArray(string sName, int nSize, location lDefault, object oTarget = OBJECT_SELF);
    void CopyLocationArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF);
    void AppendLocationArray(string sName, location lValue, object oTarget = OBJECT_SELF);
    void RemoveLocationArray(string sName, int index, object oTarget = OBJECT_SELF);
    void PrintLocationArray(string sName, object oTarget = OBJECT_SELF);

// ---------------------------------------------------------------
// -------------------------------------------------------------------



// -------------------------------------------------------------------
// ---------------------------------------------------------------

// ******************************************************
// COMMON FUNCTIONS
// ******************************************************

// ---------------------------------------------------------------
// -------------------------------------------------------------------

// This function can be used in place of the type-specific GetArray*Size()
// functions
int GetArraySize(string sName, object oTarget = OBJECT_SELF) {

    // returns the size of the array
    // * sName = name of the array
    // return 0 on error
    return GetLocalInt(oTarget, sName + "_SIZE");
}

location DefaultLocation() {
    // returns a purposely erroneous (0'd) location
    return GetLocalLocation(OBJECT_INVALID,"INVALID");
}

int GetIsArrayIndexValid(string sName, int nIndex, object oTarget = OBJECT_SELF) {

    // checks whether the index nIndex is valid for array sName
    // returns bool TRUE/FALSE

    int nSize = GetArraySize(sName,oTarget);

    return ((nIndex >= 0) && (nIndex < nSize));
}

// -------------------------------------------------------------------
// ---------------------------------------------------------------

// ******************************************************
// INTEGER ARRAYS
// ******************************************************

// ---------------------------------------------------------------
// -------------------------------------------------------------------


int GetIntArraySize(string sName, object oTarget = OBJECT_SELF) {

    // returns the size of the array
    // * sName = name of the array

    return GetLocalInt(oTarget, sName + "_SIZE");
}

void SetIntArray(string sName, int nIndex, int nValue, object oTarget = OBJECT_SELF) {
    // Sets the value of the array at slot
    // * nIndex = array slot
    // * nValue = the value to set the slot

    if ((nIndex < GetLocalInt(oTarget,sName + "_SIZE")) && (nIndex >= 0))
        SetLocalInt(oTarget,sName + "_" + IntToString(nIndex),nValue);
    else
        if (GetIntArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (SetIntArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (SetIntArray): index out of bounds (" + IntToString(nIndex) + ")");
}

int GetIntArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {
    // Gets the array's value at slot
    // * nIndex = value of slot to return

    int nReturnValue = 0;

    if ((nIndex < GetIntArraySize(sName,oTarget)) && (nIndex >= 0))
        nReturnValue = GetLocalInt(oTarget,sName + "_" + IntToString(nIndex));
    else
        if (GetIntArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (GetIntArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (GetIntArray): index out of bounds (" + IntToString(nIndex) + ")");

    return nReturnValue;

}

void CreateIntArray(string sName, int nSize, int nDefault = 0, object oTarget = OBJECT_SELF) {

    // Make an integer array.  Parameters:
    // * sName = the name of the array
    // * nSize = how big do you want the array?
    // * oTarget = on which object to create the array
    // * nDefault = the value to initialize the array to

    if (GetIntArraySize(sName,oTarget) != 0)
        WriteTimestampedLogEntry("Array API error (CreateIntArray): Array already exists (" + sName + ")");
    else {
        int i;
        for(i = 0; i < nSize; i++) SetLocalInt(oTarget,sName + "_" + IntToString(i),nDefault);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
    }
}

void ClearIntArray(string sName, int nDefault = 0, object oTarget = OBJECT_SELF) {

    // Clear all values of the array
    // * use nDefault to determine which value to which to
    //   reset the array elements

    int i;
    for (i = 0; i < GetIntArraySize(sName,oTarget); i++)
        SetIntArray(sName,i,nDefault,oTarget);
}

void DeleteIntArray(string sName, object oTarget = OBJECT_SELF) {

    // Deletes the entire array


    int i;
    for (i = 0; i < GetIntArraySize(sName,oTarget); i++)
        DeleteLocalInt(oTarget,sName + "_" + IntToString(i));
    DeleteLocalInt(oTarget,sName + "_SIZE");
}

int SearchIntArray(string sName, int nValue, object oTarget = OBJECT_SELF) {
    // returns the array index at which nValue is contained
    // * returns -1 if not found

    int i;
    for(i = 0; i < GetIntArraySize(sName,oTarget); i++)
        if (GetIntArray(sName,i,oTarget) == nValue)
            return i;

    return -1;
}

int ResizeIntArray(string sName, int nSize, int nDefault = 0, object oTarget = OBJECT_SELF) {

    // Resizes an integer array.
    // * If nSize is greater than current array size, fill the new slots with nDefault
    // * If nSize is less than current array size, delete the unused variables
    // * If nSize is invalid, generate a log error

    int i;
    int n;

    if (GetIntArraySize(sName,oTarget) < 0)
        WriteTimestampedLogEntry("Array API error (ResizeIntArray): Invalid size (" + IntToString(nSize) + ")");
    else if (GetIntArraySize(sName,oTarget) == nSize)
        WriteTimestampedLogEntry("Array API error (ResizeIntArray): No change in size (" + IntToString(nSize) + ")");
    else if (GetIntArraySize(sName,oTarget) == 0)
        DeleteIntArray(sName,oTarget);
    else if (GetIntArraySize(sName,oTarget) < nSize) {
        n = GetIntArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for (i = n; i < nSize; i++)
            SetIntArray(sName,i,nDefault,oTarget);
    }
    else if (GetIntArraySize(sName,oTarget) > nSize) {
        n = GetIntArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for(i = (n - 1); i >= nSize; i--)
            DeleteLocalInt(oTarget,sName + "_" + IntToString(i));
    }
    else WriteTimestampedLogEntry("Array API error (ResizeIntArray): Unhandled exception (" + sName + ")");

    return GetIntArraySize(sName,oTarget);
}

void CopyIntArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF) {


    // makes a copy of a location array named sSource on object oSourceTarget
    // and places it at name sDestination on oDestTarget
    // * returns error if attempting to copy onto self

    int n;
    int i;

    if ((sSource != sDestination) || (oSourceTarget != oDestTarget)) {
         n = GetIntArraySize(sSource,oSourceTarget);
         if (n > 0) {
            SetLocalInt(oDestTarget,sDestination + "_SIZE",n);
            for(i = 0; i < n; i++)
                SetIntArray(sDestination,i,GetIntArray(sSource,i,oSourceTarget),oDestTarget);
         }
         else WriteTimestampedLogEntry("Array API error (CopyIntArray): Source array size (" + sSource + ", " + IntToString(n) + ")");
    }
    else WriteTimestampedLogEntry("Array API error (CopyIntArray): destination is the same as source (" + sSource + ", " + sDestination + ")");

}

void AppendIntArray(string sName, int nValue, object oTarget = OBJECT_SELF) {

    // Adds an element at the end of the array

    ResizeIntArray(sName,(GetIntArraySize(sName) + 1),nValue,oTarget);

}

void RemoveIntArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {

    // removes the element at the given index from the list.
    // * error sprung if the index is not valid
    //
    // I haven't tested this function as much as the others.

    int i;
    int nSize = GetArraySize(sName, oTarget);

    if (GetIsArrayIndexValid(sName,nIndex)) {
        for(i = nIndex; i < (nSize-1); i++)
            SetIntArray(sName,i,GetIntArray(sName,(i + 1)),oTarget);
        DeleteLocalInt(oTarget,sName + "_" + IntToString(i));
        SetLocalInt(oTarget,sName + "_SIZE",(nSize - 1));
    }
    else WriteTimestampedLogEntry("Array API error (RemoveIntArray): array index invalid (" + IntToString(nIndex) + ")");
}

void PrintIntArray(string sName, object oTarget = OBJECT_SELF) {
    // print the contents of the array to the server log:

    WriteTimestampedLogEntry("********************");
    WriteTimestampedLogEntry("Array API: Writing contents of array");
    WriteTimestampedLogEntry("Type: int  Name: " + sName + " Size: " + IntToString(GetIntArraySize(sName,oTarget)));

    int i;
    for(i = 0; i < GetIntArraySize(sName,oTarget); i++)
        PrintInteger(GetIntArray(sName, i, oTarget));

    WriteTimestampedLogEntry("Array printing complete");
    WriteTimestampedLogEntry("********************");
}


// -------------------------------------------------------------------
// ---------------------------------------------------------------

// ******************************************************
// FLOATING POINT ARRAYS
// ******************************************************

// ---------------------------------------------------------------
// -------------------------------------------------------------------

int GetFloatArraySize(string sName, object oTarget = OBJECT_SELF) {

    // returns the size of the array
    // * sName = name of the array

    return GetLocalInt(oTarget, sName + "_SIZE");
}

void SetFloatArray(string sName, int nIndex, float fValue, object oTarget = OBJECT_SELF) {
    // Sets the value of the array at slot
    // * nIndex = array slot
    // * fValue = the value to set the slot

    if ((nIndex < GetLocalInt(oTarget,sName + "_SIZE")) && (nIndex >= 0))
        SetLocalFloat(oTarget,sName + "_" + IntToString(nIndex),fValue);
    else
        if (GetFloatArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (SetFloatArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (SetFloatArray): index out of bounds (" + IntToString(nIndex) + ")");
}

float GetFloatArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {
    // Gets the array's value at slot
    // * nIndex = value of slot to return

    float fReturnValue = 0.0;

    if ((nIndex < GetFloatArraySize(sName,oTarget)) && (nIndex >= 0))
        fReturnValue = GetLocalFloat(oTarget,sName + "_" + IntToString(nIndex));
    else
        if (GetFloatArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (GetFloatArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (GetFloatArray): index out of bounds (" + IntToString(nIndex) + ")");

    return fReturnValue;

}

void CreateFloatArray(string sName, int nSize, float fDefault = 0.0, object oTarget = OBJECT_SELF) {

    // Make a floating point array.  Parameters:
    // * sName = the name of the array
    // * nSize = how big do you want the array?
    // * oTarget = on which object to create the array
    // * fDefault = the value to initialize the array to

    if (GetFloatArraySize(sName,oTarget) != 0)
        WriteTimestampedLogEntry("Array API error (CreateFloatArray): Array already exists (" + sName + ")");
    else {
        int i;
        for(i = 0; i < nSize; i++) SetLocalFloat(oTarget,sName + "_" + IntToString(i),fDefault);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
    }
}

void ClearFloatArray(string sName, float fDefault = 0.0, object oTarget = OBJECT_SELF) {

    // Clear all values of the array
    // * use fDefault to determine which value to which to
    //   reset the array elements

    int i;
    for (i = 0; i < GetFloatArraySize(sName,oTarget); i++)
        SetFloatArray(sName,i,fDefault,oTarget);
}

void DeleteFloatArray(string sName, object oTarget = OBJECT_SELF) {

    // Deletes the entire array


    int i;
    for (i = 0; i < GetFloatArraySize(sName,oTarget); i++)
        DeleteLocalFloat(oTarget,sName + "_" + IntToString(i));
    DeleteLocalFloat(oTarget,sName + "_SIZE");
}

int SearchFloatArray(string sName, float fValue, object oTarget = OBJECT_SELF) {
    // returns the array index at which fValue is contained
    // * returns -1 if not found

    int i;
    for(i = 0; i < GetFloatArraySize(sName,oTarget); i++)
        if (GetFloatArray(sName,i,oTarget) == fValue)
            return i;

    return -1;
}

int ResizeFloatArray(string sName, int nSize, float fDefault = 0.0, object oTarget = OBJECT_SELF) {

    // Resizes a floating point array.
    // * If nSize is greater than current array size, fill the new slots with nDefault
    // * If nSize is less than current array size, delete the unused variables
    // * If nSize is invalid, generate a log error

    int i;
    int n;

    if (GetFloatArraySize(sName,oTarget) < 0)
        WriteTimestampedLogEntry("Array API error (ResizeFloatArray): Invalid size (" + IntToString(nSize) + ")");
    else if (GetFloatArraySize(sName,oTarget) == nSize)
        WriteTimestampedLogEntry("Array API error (ResizeFloatArray): No change in size (" + IntToString(nSize) + ")");
    else if (GetFloatArraySize(sName,oTarget) == 0)
        DeleteFloatArray(sName,oTarget);
    else if (GetFloatArraySize(sName,oTarget) < nSize) {
        n = GetFloatArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for (i = n; i < nSize; i++)
            SetFloatArray(sName,i,fDefault,oTarget);
    }
    else if (GetFloatArraySize(sName,oTarget) > nSize) {
        n = GetFloatArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for(i = (n - 1); i >= nSize; i--)
            DeleteLocalFloat(oTarget,sName + "_" + IntToString(i));
    }
    else WriteTimestampedLogEntry("Array API error (ResizeFloatArray): Unhandled exception (" + sName + ")");

    return GetFloatArraySize(sName,oTarget);
}

void CopyFloatArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF) {

    // makes a copy of a location array named sSource on object oSourceTarget
    // and places it at name sDestination on oDestTarget
    // * returns error if attempting to copy onto self

    int n;
    int i;

    if ((sSource != sDestination) || (oSourceTarget != oDestTarget)) {

         n = GetFloatArraySize(sSource,oSourceTarget);
         if (n > 0) {
            SetLocalInt(oDestTarget,sDestination + "_SIZE",n);
            for(i = 0; i < n; i++)
                SetFloatArray(sDestination,i,GetFloatArray(sSource,i,oSourceTarget),oDestTarget);
         }
         else WriteTimestampedLogEntry("Array API error (CopyFloatArray): Source array size (" + sSource + ", " + IntToString(n) + ")");
    }
    else WriteTimestampedLogEntry("Array API error (CopyFloatArray): destination is the same as source (" + sSource + ", " + sDestination + ")");

}

void AppendFloatArray(string sName, float fValue, object oTarget = OBJECT_SELF) {

    // Adds an element at the end of the array

    ResizeFloatArray(sName,(GetFloatArraySize(sName) + 1),fValue,oTarget);

}

void RemoveFloatArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {

    int i;
    int nSize = GetArraySize(sName, oTarget);

    if (GetIsArrayIndexValid(sName,nIndex)) {
        for(i = nIndex; i < (nSize-1); i++)
            SetFloatArray(sName,i,GetFloatArray(sName,(i + 1)),oTarget);
        DeleteLocalFloat(oTarget,sName + "_" + IntToString(i));
        SetLocalInt(oTarget,sName + "_SIZE",(nSize - 1));
    }
    else WriteTimestampedLogEntry("Array API error (RemoveFloatArray): array index invalid (" + IntToString(nIndex) + ")");
}


void PrintFloatArray(string sName, object oTarget = OBJECT_SELF) {
    // print the contents of the array to the server log:

    WriteTimestampedLogEntry("********************");
    WriteTimestampedLogEntry("Array API: Writing contents of array");
    WriteTimestampedLogEntry("Type: Float  Name: " + sName + " Size: " + IntToString(GetFloatArraySize(sName,oTarget)));

    int i;
    for(i = 0; i < GetFloatArraySize(sName,oTarget); i++)
        PrintFloat(GetFloatArray(sName, i, oTarget));

    WriteTimestampedLogEntry("Array printing complete");
    WriteTimestampedLogEntry("********************");
}


// -------------------------------------------------------------------
// ---------------------------------------------------------------

// ******************************************************
// STRING ARRAYS
// ******************************************************

// ---------------------------------------------------------------
// -------------------------------------------------------------------

int GetStringArraySize(string sName, object oTarget = OBJECT_SELF) {

    // returns the size of the array
    // * sName = name of the array

    return GetLocalInt(oTarget, sName + "_SIZE");
}

void SetStringArray(string sName, int nIndex, string sValue, object oTarget = OBJECT_SELF) {
    // Sets the value of the array at slot
    // * nIndex = array slot
    // * sValue = the value to set the slot

    if ((nIndex < GetLocalInt(oTarget,sName + "_SIZE")) && (nIndex >= 0))
        SetLocalString(oTarget,sName + "_" + IntToString(nIndex),sValue);
    else
        if (GetStringArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (SetStringArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (SetStringArray): index out of bounds (" + IntToString(nIndex) + ")");
}

string GetStringArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {
    // Gets the array's value at slot
    // * nIndex = value of slot to return

    string sReturnValue = "";

    if ((nIndex < GetStringArraySize(sName,oTarget)) && (nIndex >= 0))
       sReturnValue = GetLocalString(oTarget,sName + "_" + IntToString(nIndex));
    else
        if (GetStringArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (GetStringArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (GetStringArray): index out of bounds (" + IntToString(nIndex) + ")");

    return sReturnValue;

}

void CreateStringArray(string sName, int nSize, string sDefault = "", object oTarget = OBJECT_SELF) {

    // Make a string array.  Parameters:
    // * sName = the name of the array
    // * nSize = how big do you want the array?
    // * oTarget = on which object to create the array
    // * sDefault = the value to initialize the array to

    if (GetStringArraySize(sName,oTarget) != 0)
        WriteTimestampedLogEntry("Array API error (CreateStringArray): Array already exists (" + sName + ")");
    else {
        int i;
        for(i = 0; i < nSize; i++) SetLocalString(oTarget,sName + "_" + IntToString(i),sDefault);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
    }
}

void ClearStringArray(string sName, string sDefault = "", object oTarget = OBJECT_SELF) {

    // Clear all values of the array
    // * use sDefault to determine which value to which to
    //   reset the array elements

    int i;
    for (i = 0; i < GetStringArraySize(sName,oTarget); i++)
        SetStringArray(sName,i,sDefault,oTarget);
}

void DeleteStringArray(string sName, object oTarget = OBJECT_SELF) {

    // Deletes the entire array

    int i;
    for (i = 0; i < GetStringArraySize(sName,oTarget); i++)
        DeleteLocalString(oTarget,sName + "_" + IntToString(i));
    DeleteLocalInt(oTarget,sName + "_SIZE");
}

int SearchStringArray(string sName, string sValue, object oTarget = OBJECT_SELF) {
    // returns the array index at which sValue is contained
    // * returns -1 if not found

    int i;
    for(i = 0; i < GetStringArraySize(sName,oTarget); i++)
        if (GetStringArray(sName,i,oTarget) == sValue)
            return i;

    return -1;
}

int ResizeStringArray(string sName, int nSize, string sDefault = "", object oTarget = OBJECT_SELF) {

    // Resizes a string array.
    // * If nSize is greater than current array size, fill the new slots with nDefault
    // * If nSize is less than current array size, delete the unused variables
    // * If nSize is invalid, generate a log error

    int i;
    int n;

    if (GetStringArraySize(sName,oTarget) < 0)
        WriteTimestampedLogEntry("Array API error (ResizeStringArray): Invalid size (" + IntToString(nSize) + ")");
    else if (GetStringArraySize(sName,oTarget) == nSize)
        WriteTimestampedLogEntry("Array API error (ResizeStringArray): No change in size (" + IntToString(nSize) + ")");
    else if (GetStringArraySize(sName,oTarget) == 0)
        DeleteStringArray(sName,oTarget);
    else if (GetStringArraySize(sName,oTarget) < nSize) {
        n = GetStringArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for (i = n; i < nSize; i++)
            SetStringArray(sName,i,sDefault,oTarget);
    }
    else if (GetStringArraySize(sName,oTarget) > nSize) {
        n = GetStringArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for(i = (n - 1); i >= nSize; i--)
            DeleteLocalString(oTarget,sName + "_" + IntToString(i));
    }
    else WriteTimestampedLogEntry("Array API error (ResizeStringArray): Unhandled exception (" + sName + ")");

    return GetStringArraySize(sName,oTarget);
}

void CopyStringArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF) {

    // makes a copy of a location array named sSource on object oSourceTarget
    // and places it at name sDestination on oDestTarget
    // * returns error if attempting to copy onto self

    int n;
    int i;

    if ((sSource != sDestination) || (oSourceTarget != oDestTarget)) {

         n = GetStringArraySize(sSource,oSourceTarget);
         if (n > 0) {
            SetLocalInt(oDestTarget,sDestination + "_SIZE",n);
            for(i = 0; i < n; i++)
                SetStringArray(sDestination,i,GetStringArray(sSource,i,oSourceTarget),oDestTarget);
         }
         else WriteTimestampedLogEntry("Array API error (CopyStringArray): Source array size (" + sSource + ", " + IntToString(n) + ")");
    }
    else WriteTimestampedLogEntry("Array API error (CopyStringArray): destination is the same as source (" + sSource + ", " + sDestination + ")");

}

void AppendStringArray(string sName, string sValue, object oTarget = OBJECT_SELF) {

    // Adds an element at the end of the array

    ResizeStringArray(sName,(GetStringArraySize(sName) + 1),sValue,oTarget);

}

void RemoveStringArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {

    int i;
    int nSize = GetArraySize(sName, oTarget);

    if (GetIsArrayIndexValid(sName,nIndex)) {
        for(i = nIndex; i < (nSize-1); i++)
            SetStringArray(sName,i,GetStringArray(sName,(i + 1)),oTarget);
        DeleteLocalString(oTarget,sName + "_" + IntToString(i));
        SetLocalInt(oTarget,sName + "_SIZE",(nSize - 1));
    }
    else WriteTimestampedLogEntry("Array API error (RemoveStringArray): array index invalid (" + IntToString(nIndex) + ")");
}


void PrintStringArray(string sName, object oTarget = OBJECT_SELF) {
    // print the contents of the array to the server log:

    WriteTimestampedLogEntry("********************");
    WriteTimestampedLogEntry("Array API: Writing contents of array");
    WriteTimestampedLogEntry("Type: string  Name: " + sName + " Size: " + IntToString(GetStringArraySize(sName,oTarget)));

    int i;
    for(i = 0; i < GetStringArraySize(sName,oTarget); i++)
        PrintString(GetStringArray(sName, i, oTarget));

    WriteTimestampedLogEntry("Array printing complete");
    WriteTimestampedLogEntry("********************");
}


// -------------------------------------------------------------------
// ---------------------------------------------------------------

// ******************************************************
// OBJECT ARRAYS
// ******************************************************

// ---------------------------------------------------------------
// -------------------------------------------------------------------


int GetObjectArraySize(string sName, object oTarget = OBJECT_SELF) {

    // returns the size of the array
    // * sName = name of the array

    return GetLocalInt(oTarget, sName + "_SIZE");
}

void SetObjectArray(string sName, int nIndex, object oValue, object oTarget = OBJECT_SELF) {
    // Sets the value of the array at slot
    // * nIndex = array slot
    // * oValue = the value to set the slot

    if ((nIndex < GetLocalInt(oTarget,sName + "_SIZE")) && (nIndex >= 0))
        SetLocalObject(oTarget,sName + "_" + IntToString(nIndex),oValue);
    else
        if (GetObjectArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (SetObjectArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (SetObjectArray): index out of bounds (" + IntToString(nIndex) + ")");
}

object GetObjectArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {
    // Gets the array's value at slot
    // * nIndex = value of slot to return

    object oReturnValue = OBJECT_INVALID;

    if ((nIndex < GetObjectArraySize(sName,oTarget)) && (nIndex >= 0))
        oReturnValue = GetLocalObject(oTarget,sName + "_" + IntToString(nIndex));
    else
        if (GetObjectArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (GetObjectArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (GetObjectArray): index out of bounds (" + IntToString(nIndex) + ")");

    return oReturnValue;

}

void CreateObjectArray(string sName, int nSize, object oDefault = OBJECT_INVALID, object oTarget = OBJECT_SELF) {

    // Make an object array.  Parameters:
    // * sName = the name of the array
    // * nSize = how big do you want the array?
    // * oTarget = on which object to create the array
    // * oDefault = the value to initialize the array to

    if (GetObjectArraySize(sName,oTarget) != 0)
        WriteTimestampedLogEntry("Array API error (CreateObjectArray): Array already exists (" + sName + ")");
    else {
        int i;
        for(i = 0; i < nSize; i++) SetLocalObject(oTarget,sName + "_" + IntToString(i),oDefault);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
    }
}

void ClearObjectArray(string sName, object oDefault = OBJECT_INVALID, object oTarget = OBJECT_SELF) {

    // Clear all values of the array
    // * use nDefault to determine which value to which to
    //   reset the array elements

    int i;
    for (i = 0; i < GetObjectArraySize(sName,oTarget); i++)
        SetObjectArray(sName,i,oDefault,oTarget);
}

void DeleteObjectArray(string sName, object oTarget = OBJECT_SELF) {

    // Deletes the entire array


    int i;
    for (i = 0; i < GetObjectArraySize(sName,oTarget); i++)
        DeleteLocalObject(oTarget,sName + "_" + IntToString(i));
    DeleteLocalInt(oTarget,sName + "_SIZE");
}

int SearchObjectArray(string sName, object oValue, object oTarget = OBJECT_SELF) {
    // returns the array index at which oValue is contained
    // * returns -1 if not found

    int i;
    for(i = 0; i < GetObjectArraySize(sName,oTarget); i++)
        if (GetObjectArray(sName,i,oTarget) == oValue)
            return i;

    return -1;
}

int ResizeObjectArray(string sName, int nSize, object oDefault = OBJECT_INVALID, object oTarget = OBJECT_SELF) {

    // Resizes an object array.
    // * If nSize is greater than current array size, fill the new slots with nDefault
    // * If nSize is less than current array size, delete the unused variables
    // * If nSize is invalid, generate a log error

    int i;
    int n;

    if (GetObjectArraySize(sName,oTarget) < 0)
        WriteTimestampedLogEntry("Array API error (ResizeObjectArray): Invalid size (" + IntToString(nSize) + ")");
    else if (GetObjectArraySize(sName,oTarget) == nSize)
        WriteTimestampedLogEntry("Array API error (ResizeObjectArray): No change in size (" + IntToString(nSize) + ")");
    else if (GetObjectArraySize(sName,oTarget) == 0)
        DeleteObjectArray(sName,oTarget);
    else if (GetObjectArraySize(sName,oTarget) < nSize) {
        n = GetObjectArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for (i = n; i < nSize; i++)
            SetObjectArray(sName,i,oDefault,oTarget);
    }
    else if (GetObjectArraySize(sName,oTarget) > nSize) {
        n = GetObjectArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for(i = (n - 1); i >= nSize; i--)
            DeleteLocalObject(oTarget,sName + "_" + IntToString(i));
    }
    else WriteTimestampedLogEntry("Array API error (ResizeObjectArray): Unhandled exception (" + sName + ")");

    return GetObjectArraySize(sName,oTarget);
}

void CopyObjectArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF) {


    // makes a copy of a location array named sSource on object oSourceTarget
    // and places it at name sDestination on oDestTarget
    // * returns error if attempting to copy onto self

    int n;
    int i;

    if ((sSource != sDestination) || (oSourceTarget != oDestTarget)) {

         n = GetObjectArraySize(sSource,oSourceTarget);
         if (n > 0) {
            SetLocalInt(oDestTarget,sDestination + "_SIZE",n);
            for(i = 0; i < n; i++)
                SetObjectArray(sDestination,i,GetObjectArray(sSource,i,oSourceTarget),oDestTarget);
         }
         else WriteTimestampedLogEntry("Array API error (CopyObjectArray): Source array size (" + sSource + ", " + IntToString(n) + ")");
    }
    else WriteTimestampedLogEntry("Array API error (CopyObjectArray): destination is the same as source (" + sSource + ", " + sDestination + ")");

}

void AppendObjectArray(string sName, object oValue, object oTarget = OBJECT_SELF) {

    // Adds an element at the end of the array

    ResizeObjectArray(sName,(GetObjectArraySize(sName) + 1),oValue,oTarget);

}

void RemoveObjectArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {

    int i;
    int nSize = GetArraySize(sName, oTarget);

    if (GetIsArrayIndexValid(sName,nIndex)) {
        for(i = nIndex; i < (nSize-1); i++)
            SetObjectArray(sName,i,GetObjectArray(sName,(i + 1)),oTarget);
        DeleteLocalObject(oTarget,sName + "_" + IntToString(i));
        SetLocalInt(oTarget,sName + "_SIZE",(nSize - 1));
    }
    else WriteTimestampedLogEntry("Array API error (RemoveObjectArray): array index invalid (" + IntToString(nIndex) + ")");
}


void PrintObjectArray(string sName, object oTarget = OBJECT_SELF) {
    // print the contents of the array to the server log:

    WriteTimestampedLogEntry("********************");
    WriteTimestampedLogEntry("Array API: Writing contents of array");
    WriteTimestampedLogEntry("Type: Object  Name: " + sName + " Size: " + IntToString(GetIntArraySize(sName,oTarget)));

    int i;
    for(i = 0; i < GetObjectArraySize(sName,oTarget); i++)
        PrintObject(GetObjectArray(sName, i, oTarget));

    WriteTimestampedLogEntry("Array printing complete");
    WriteTimestampedLogEntry("********************");
}


// -------------------------------------------------------------------
// ---------------------------------------------------------------

// ******************************************************
// LOCATION ARRAYS
// ******************************************************

// ---------------------------------------------------------------
// -------------------------------------------------------------------


int GetLocationArraySize(string sName, object oTarget = OBJECT_SELF) {

    // returns the size of the array
    // * sName = name of the array

    return GetLocalInt(oTarget, sName + "_SIZE");
}

void SetLocationArray(string sName, int nIndex, location lValue, object oTarget = OBJECT_SELF) {
    // Sets the value of the array at slot
    // * nIndex = array slot
    // * lValue = the value to set the slot

    if ((nIndex < GetLocalInt(oTarget,sName + "_SIZE")) && (nIndex >= 0))
        SetLocalLocation(oTarget,sName + "_" + IntToString(nIndex),lValue);
    else
        if (GetLocationArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (SetObjectArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (SetLocationArray): index out of bounds (" + IntToString(nIndex) + ")");
}

location GetLocationArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {
    // Gets the array's value at slot
    // * nIndex = value of slot to return

    location lReturnValue = GetLocalLocation(OBJECT_INVALID,"DEFAULT");

    if ((nIndex < GetLocationArraySize(sName,oTarget)) && (nIndex >= 0))
       lReturnValue = GetLocalLocation(oTarget,sName + "_" + IntToString(nIndex));
    else
        if (GetLocationArraySize(sName,oTarget) == 0)
            WriteTimestampedLogEntry("Array API error (GetLocationArray): array size 0 (or array does not exist) (" + sName + ")");
        else WriteTimestampedLogEntry("Array API error (GetLocationArray): index out of bounds (" + IntToString(nIndex) + ")");

    return lReturnValue;

}

void CreateLocationArray(string sName, int nSize, location lDefault, object oTarget = OBJECT_SELF) {

    // Make a location array.  Parameters:
    // * sName = the name of the array
    // * nSize = how big do you want the array?
    // * oTarget = on which location to create the array
    // * lDefault = the value to initialize the array to

    if (GetLocationArraySize(sName,oTarget) != 0)
        WriteTimestampedLogEntry("Array API error (CreateLocationArray): Array already exists (" + sName + ")");
    else {
        int i;
        for(i = 0; i < nSize; i++) SetLocalLocation(oTarget,sName + "_" + IntToString(i),lDefault);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
    }
}

void ClearLocationArray(string sName, location lDefault, object oTarget = OBJECT_SELF) {

    // Clear all values of the array
    // * use lDefault to determine which value to which to
    //   reset the array elements

    int i;
    for (i = 0; i < GetLocationArraySize(sName,oTarget); i++)
        SetLocationArray(sName,i,lDefault,oTarget);
}

void DeleteLocationArray(string sName, object oTarget = OBJECT_SELF) {

    // Deletes the entire array

    int i;
    for (i = 0; i < GetLocationArraySize(sName,oTarget); i++)
        DeleteLocalLocation(oTarget,sName + "_" + IntToString(i));
    DeleteLocalInt(oTarget,sName + "_SIZE");
}

int SearchLocationArray(string sName, location lValue, object oTarget = OBJECT_SELF) {
    // returns the array index at which nValue is contained
    // * returns -1 if not found

    int i;
    for(i = 0; i < GetLocationArraySize(sName,oTarget); i++)
        if (GetLocationArray(sName,i,oTarget) == lValue)
            return i;

    return -1;
}

int ResizeLocationArray(string sName, int nSize, location lDefault, object oTarget = OBJECT_SELF) {

    // Resizes a location array.
    // * If nSize is greater than current array size, fill the new slots with nDefault
    // * If nSize is less than current array size, delete the unused variables
    // * If nSize is invalid, generate a log error

    int i;
    int n;

    if (GetLocationArraySize(sName,oTarget) < 0)
        WriteTimestampedLogEntry("Array API error (ResizeLocationArray): Invalid size (" + IntToString(nSize) + ")");
    else if (GetLocationArraySize(sName,oTarget) == nSize)
        WriteTimestampedLogEntry("Array API error (ResizeLocationArray): No change in size (" + IntToString(nSize) + ")");
    else if (GetLocationArraySize(sName,oTarget) == 0)
        DeleteLocationArray(sName,oTarget);
    else if (GetLocationArraySize(sName,oTarget) < nSize) {
        n = GetLocationArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for (i = n; i < nSize; i++)
            SetLocationArray(sName,i,lDefault,oTarget);
    }
    else if (GetLocationArraySize(sName,oTarget) > nSize) {
        n = GetLocationArraySize(sName,oTarget);
        SetLocalInt(oTarget,sName + "_SIZE",nSize);
        for(i = (n - 1); i >= nSize; i--)
            DeleteLocalLocation(oTarget,sName + "_" + IntToString(i));
    }
    else WriteTimestampedLogEntry("Array API error (ResizeLocationArray): Unhandled exception (" + sName + ")");

    return GetLocationArraySize(sName,oTarget);
}

void CopyLocationArray(string sSource, string sDestination, object oSourceTarget = OBJECT_SELF, object oDestTarget = OBJECT_SELF) {

    // makes a copy of a location array named sSource on object oSourceTarget
    // and places it at name sDestination on oDestTarget
    // * returns error if attempting to copy onto self

    int n;
    int i;

    if ((sSource != sDestination) || (oSourceTarget != oDestTarget)) {
         n = GetLocationArraySize(sSource,oSourceTarget);
         if (n > 0) {
            SetLocalInt(oDestTarget,sDestination + "_SIZE",n);
            for(i = 0; i < n; i++)
                SetLocationArray(sDestination,i,GetLocationArray(sSource,i,oSourceTarget),oDestTarget);
         }
         else WriteTimestampedLogEntry("Array API error (CopyLocationArray): Source array size (" + sSource + ", " + IntToString(n) + ")");
    }
    else WriteTimestampedLogEntry("Array API error (CopyLocationArray): destination is the same as source (" + sSource + ", " + sDestination + ")");

}

void AppendLocationArray(string sName, location lValue, object oTarget = OBJECT_SELF) {

    // Adds an element at the end of the array

    ResizeLocationArray(sName,(GetLocationArraySize(sName) + 1),lValue,oTarget);

}

void RemoveLocationArray(string sName, int nIndex, object oTarget = OBJECT_SELF) {

    int i;
    int nSize = GetArraySize(sName, oTarget);

    if (GetIsArrayIndexValid(sName,nIndex)) {
        for(i = nIndex; i < (nSize-1); i++)
            SetLocationArray(sName,i,GetLocationArray(sName,(i + 1)),oTarget);
        DeleteLocalLocation(oTarget,sName + "_" + IntToString(i));
        SetLocalInt(oTarget,sName + "_SIZE",(nSize - 1));
    }
    else WriteTimestampedLogEntry("Array API error (RemoveLocationArray): array index invalid (" + IntToString(nIndex) + ")");
}


void PrintLocationArray(string sName, object oTarget = OBJECT_SELF) {
    // print the contents of the array to the server log:

    WriteTimestampedLogEntry("********************");
    WriteTimestampedLogEntry("Array API: Writing contents of array");
    WriteTimestampedLogEntry("Type: Location  Name: " + sName + " Size: " + IntToString(GetLocationArraySize(sName,oTarget)));

    int i;
    for(i = 0; i < GetLocationArraySize(sName,oTarget); i++)
        PrintVector(GetPositionFromLocation(GetLocationArray(sName, i, oTarget)), FALSE);

    WriteTimestampedLogEntry("Array printing complete");
    WriteTimestampedLogEntry("********************");
}


// -------------------------------------------------------------------
// -------------------------------------------------------------------
// -------------------------------------------------------------------

// eof