Jump to content

Photo

Template for Global Arrays, and Functions that Use Arrays

arrays global template

  • Please log in to reply
7 replies to this topic

#1 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 20 April 2014 - 10:08 AM

Global Arrays

I know that I'm going to need to use some global arrays to handle skill checks, and such, in my project; but I have no example to use as a guideline for this.

In the project for which I need then, each array would have 256 values in it, with each value matching an item editor value. Note, that I don't need an example that includes 256 values:  Producing an example set of arrays and functions that use them, to store values, reset values, etc., as a template, I would appreciate it greatly. As I said, I don't need to see an example array with 256 values, but something with say, ten values, would be fine, because expanding it, once I know how it works, is easy for me.

 

Once I have a template from which I can work, I can do some pretty amazing things, but working without any living example is very hard, as I am an extremely visual person. I don't even know what the maximum number of values that can be stored in an array is in ZScript.

 

My Intended Usage

 

This is something that I need to use, in order to actually implement a skill check system, because otherwise, I't need hundreds of global variables, just to track checks, failures, and successes.

 

While many items wont use these values initially, I think it would be easier to track all 256 possible values, than to only use the values that I need, because if any of them change, then the work involved with fixing all the functions that are tied to them is absurdly convoluted.

If it is just a numeric list of 0 through 255, then anything that calls to them can be easily translated using the item number value, and if I add items, or change items, the function will remain the same. item 121, will always be the 121st array value, in any set of arrays, and related functions, that work in this manner.

The way that I will need this to work, is to store a value of 0, 1, 2, or 3, for each item in the game (arrayItemLore), in an array; and a value of 0, 1, or 2, for each item, in a second array (arrayChecked).

Then, if Link makes a Lore check on the item, first, the game sets the vale tied to that item in arrayChecked to 1, because he has made a Lore check attempt] a failure sets the value from 0 to 1, and a success sets the value from 0 to 2.

If the value of this part of the arrayChecked is 2, then the value stored in arrayItemLore, for that one item, increases by 1, which triggers a secondary function, that upgrades the item, displays strings, makes fanfare, etc..

If he fails, the value for that item in the arrayChecked array is set to 1, and any new attempt to check that item will report something like 'You must improve your skill before you may make a new Lore Skill Check on this item'.

Either way, if the value is not 0 then the player can't make a new check until the value in arrayChecked is reset to 0.

Gaining a level would reset all values in arrayChecked to 0, to allow new checks on items when your Lore skill increases. I will probably need to make a variety of these arrays, to track items, places, people, and other lore, but what I really need is a working, living example of how to make global arrays, and functions that use them, including reading from, and writing to the array values.

That's the basic idea. I'd appreciate a sampling of example global arrays, and functions that use them. Thank you all for your time, and consideration.

 

P.S. Examples that don;t include separate functions to read from a global array, and to write to a global array, will not be helpful to me; and examples that aren't actually functional also aren't useful. What I need to have in order to do this, is a working example of handling global arrays, that includes reading values from them, and writing values to them, using global functions. 


Edited by ZoriaRPG, 20 April 2014 - 10:12 AM.


#2 anikom15

anikom15

    Dictator

  • Banned
  • Real Name:Westley
  • Location:California, United States

Posted 20 April 2014 - 10:42 AM

Arrays are complicated and much time is spent studying how to manipulate them. You don't need functions to read or write to them. Just remember that their size is fixed and they are always passed by reference. Since there is no dynamic allocation in ZScript, returning an array through a function is impossible.

#3 Alucard648

Alucard648

    Magus

  • Members
  • Location:castle Dracula

Posted 20 April 2014 - 10:44 AM

I don`t know everything about global arrays. But it seems to me that a single global array of 256 variables instantly eats up entire global var limit.


Edited by Alucard648, 20 April 2014 - 10:45 AM.


#4 Saffith

Saffith

    IPv7 user

  • Members

Posted 20 April 2014 - 11:21 AM

A global array only counts as one global variable. You can have an array of up to 214747 elements - the largest integer literal ZScript allows.

I handle such things like this:
// Offsets
const int ITEM_FAMILY = 0;
const int ITEM_LEVEL = 1;
const int ITEM_POWER = 2;
const int ITEM_CSET = 3;
// And so on

const int SIZEOF_ITEM = 4; // Max data offset+1

float Item_Data[1024]; // SIZEOF_ITEM * number of items

int Item_GetFamily(int id)
{
    return Item_Data[id*SIZEOF_ITEM+ITEM_FAMILY];
}

void Item_SetFamily(int id, int value)
{
    Item_Data[id*SIZEOF_ITEM+ITEM_FAMILY]=value;
}

int Item_GetPower(int id)
{
    return Item_Data[id*SIZEOF_ITEM+ITEM_POWER];
}

void Item_SetPower(int id, int value)
{
    Item_Data[id*SIZEOF_ITEM+ITEM_POWER]=value;
}

// And so forth.

// Alternatively, generic functions:

int Item_GetData(int id, int data)
{
    return Item_Data[id*SIZEOF_ITEM+data];
}

void Item_SetData(int id, int data, int value)
{
    Item_Data[id*SIZEOF_ITEM+data]=value;
}
There are a lot of possible variations on that, but that's the basic idea.

#5 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 May 2014 - 08:57 AM

This is what I have in mind: Please let me know if what I'm trying to do is wrong, or otherwise impossible:
 
const int loreCheckItem_FFC_Slot = 1; //Sets FFC slot for FFC to execute check.
int CR_ItemLore = 0;
const int messageNeedALevel = 100;

void loreCheck(
    bool success,
    int item001, int item001_levelUnlocked, int item001_lastChecked, int item001_nextCheck, int item001_messageFailure, int item001_messageSuccess, int item001_upgrade, int item 001_result,
    int item002, int item002_levelUnlocked, int item002_lastChecked, int item002_nextCheck, int item002_messageFailure, int item002_messageSuccess, int item002_upgrade, int item_002_result,
    int item003, int item003_levelUnlocked, int item003_lastChecked, int item003_nextCheck, int item003_messageFailure, int item003_messageSuccess, int item003_upgrade, int item_002_result,
    int item004, int item004_levelUnlocked, int item004_lastChecked, int item004_nextCheck, int item004_messageFailure, int item004_messageSuccess, int item004_upgrade, int item_004_result,
    ) {

    // item### is the item number for the Lore Check.
    // _levelUnlocked is the level of the item at present.
    // _lastchecked is the player level in game, when the last check was made.
    // _nextCheck is the level the player must be before retrying a check.
    // _messageFailure is the string to play on a FAILED skill check.
    // _messageSuccess is the string to pay on a SUCCESSFUL skill check.
    // _upgrade is the item to give the player on a successful skill check.
    // _result is the flag to set or other outcome of a success.

    
    int loreSkill = CR_ItemLore;
    int loreSkillBase = loreSkill * 10;
    int loreSkillmodifier = Game->counter[CR_MIND] / 2;
    int loreSkillTotal = loreSkillBase + loreSkillmodifier;
    
    int item001 = 1;
    int item002 = 2;
    int item002 = 3;
    int item004 = 4;
    
    int loreCheck = rolldie(100); //Makes actual check.
    
    if ( loreCheck < loreSkillTotal ) {
        success = true;
        }
    else if ( loreCheck >= loreSkillTotal ) {
        success = false;
        }



    if(CountFFCsRunning(loreCheckItem_FFC_Slot) == 0) {
        int args[33] = {
        success,
        item001, item001_levelUnlocked, item001_lastChecked, item001_nextCheck, item001_messageFailure, item001_messageSuccess, item001_upgrade, item 001_result,
        item002, item002_levelUnlocked, item002_lastChecked, item002_nextCheck, item002_messageFailure, item002_messageSuccess, item002_upgrade, item_002_result,
        item003, item003_levelUnlocked, item003_lastChecked, item003_nextCheck, item003_messageFailure, item003_messageSuccess, item003_upgrade, item_002_result,
        item004, item004_levelUnlocked, item004_lastChecked, item004_nextCheck, item004_messageFailure, item004_messageSuccess, item004_upgrade, item_004_result
        };
        
        RunFFCScript(loreCheckItem_FFC_Slot, args);    
        }    
}
                
ffc script loreCheck{
	void run(
    bool success;
    int item;
    int item001, int item001_levelUnlocked, int item001_lastChecked, int item001_nextCheck, int item001_messageFailure, int item001_messageSuccess, int item001_upgrade, int item 001_result,
    int item002, int item002_levelUnlocked, int item002_lastChecked, int item002_nextCheck, int item002_messageFailure, int item002_messageSuccess, int item002_upgrade, int item_002_result,
    int item003, int item003_levelUnlocked, int item003_lastChecked, int item003_nextCheck, int item003_messageFailure, int item003_messageSuccess, int item003_upgrade, int item_002_result,
    int item004, int item004_levelUnlocked, int item004_lastChecked, int item004_nextCheck, int item004_messageFailure, int item004_messageSuccess, int item004_upgrade, int item_004_result,
    int levelToUnlock
    ) {
    
    int thisCheckAtLevel = Game->Counter[CR_LEVEL];
    
    GetCurrentA();
    
    if ( item == item001 ){
        if ( item001LastChecked < Game->Counter[CR_LEVEL] ) {
            if (success == true ) {
                item001_levelUnlocked += 1;
                
                int upgrade = item001_upgrade;
                int result = item 001_result;
                int args[4] = {item, levelToUnlock, upgrade, result};
                    unlockItem(item, levelToUnlock, upgrade, result);
                    Screen->Message(item001_messageSuccess);
                    }
                    
                if (success == false ) {
                    item001_nextCheck += 1;
                    Screen->Message(item001_messageFailure);
                    }
                        
                    
                }
            
            if ( item001LastChecked >= Game->Counter[CR_LEVEL] ) {
                Screen->Message(messageNeedALevel);
                }
                
        }
    }
}

void unlockItem(int item, int levelToUnlock, int upgrade, int result){
}
I may separate each item number check into a single function, to make it easier to handle, or otherwise read the item number of an item selected in a menu, to check, and use a specific function call via that menu, so the main function would be void LoreCheckItem001() , or something like that, obviously naming the 001 part with the item name, once I have set it up.

I think that what I'm doing should pass the values between functions and using an FFC script should allow for values to be returned, if needed. (I'm passing the values to an FFC, so that if I need to return them into a function, I can.)

One thing that I don't know: is an uninitialised declaration defaulted to a value of zero, or do I need to declare these values for each item, starting at zero, for each function and array set?

Keep in mind that I'm trying to save global values here, so I may need a master array, setting the values all to specific numbers, but this is the kind of framework that I'm describing.

I'll probably set up the main array to store the vales for 128 items (more than needed at present, but it allows for expansion), so that is 128 * 8 (1024) elements in total. A nightmare to handle, but I would otherwise need 1,024 additional globao values to do this in any other manner. Even if I use bitwise operations for this kind of task, I think I'd easily run out of globals. (If there is ever a ZC 2.6, a gigantic global cap, such as 4,096 globals, would be on my wish-list.)

Edited by ZoriaRPG, 01 May 2014 - 09:04 AM.


#6 Saffith

Saffith

    IPv7 user

  • Members

Posted 01 May 2014 - 11:51 AM

An FFC script can't take more than eight arguments, even if it's set up by another script. You'll have to come up with something else for that.

A big global array isn't too bad to deal with if you structure it properly and access it through functions. It can be a bit slow if you use it heavily, since every time you access it, you have to calculate the index, and then ZC has to dereference it and check the bounds. That shouldn't be a problem in practice, but it's something to keep in mind.
 

One thing that I don't know: is an uninitialised declaration defaulted to a value of zero, or do I need to declare these values for each item, starting at zero, for each function and array set?

Everything is initialized to 0 automatically.

#7 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 May 2014 - 12:04 PM

Can I use a single int for a global array, instead of FFCs, to handle the arguments, with the ability to return information?

 

If not, what would be the best way to handle this, if I need to process returns?

 

Otherwise, I presume that I am passing elements and arguments properly. Is that right?

 

One of my reasons for opting to use an FFC script, was because I am using both bools and ints, and I know that I cant typecast a bool into an int; but I can use flags in int format, instead of a bool if needed.

 

I also thought that an FFC would be useful for running code from menus, and I could probably use that as the last step of the process, where a return is most needed, by passing only the necessary values (eight total) into it.

 

BTW, Saffith, what do you use for making strings, to use with Tango and the Tango control codes?

 

I've been reading the documentation, and my primary set-back is that to write strings with code in them, is a huge pain in the 'tank turret' view of ZQ. Do you have a string editor of your own?

 

I would also appreciate knowing if I am using the latest Tango version: Tango Beta-1, from your OP in the Tango.zh thread. A how-to topic, showing step-by-step details on setting up, and using slots would also be amazing, as by reading the different Tango files, I see all these levels of initialisation, but I don;t know how I'm supposed to organise. and nest them.

 

I was thinking that it may be possible to hard-code a string into a script, and use some kind of append function to add it to a blank string (e.g. String 0), so that I can bypass the string editor, and contain all strings in an easy to use format. I would love an echo function in Tango, as this would dramatically simplify using strings. (Something that reads strings, from a plain text file, as part of a script set, and uses them to control Tango functions, (such as echo, SetString, whatever.)


Edited by ZoriaRPG, 01 May 2014 - 12:13 PM.


#8 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 23 May 2014 - 01:01 AM

My apologies in advance, for the double-post: I'm bumping this, to thank all of you, for your time, and patience.

 

Now, I feel I have a slid grasp of array tables, and using functions to read fro, write to, and otherwise manipulate arrays. I have made several int arrays, and a few bool arrays thus far, that all work as intended.

 

Thank you all again, for your replies, and the time that you spent working with me!

 

The sick part, is that all that everyone said to me snapped into place when I saw one, small array, and made one myself. It was one of those moments of perfect clarity, when all the random elements just re-arranged in my mind, to give me comprehension on how these methods work, and what the calculation (e.g. as those posted by Saffith) work.

 

Seeing a list of constants, and some arrays, didn't mean much, because they had no context, but once I saw usage in context--shockingly with a three-element array), I understood exactly what you were doing. At that point, everything that you explained clicked, and I've made some array tables (virtual structures), that actually work, as I intend, which has allowed me to condense related globals in many instances.

 

I may be a bit thick at times, mostly due to being a very visually minded person; so seeing a fully-working example was exactly what I needed to comprehend this. All the lectures in the world, if incomplete (i.e. lacking explicit examples), often do naught to help me, but one explicit example, or a detailed explanation, does wonders to improving my comprehension. My programming background is vastly different to that of modern languages, but I do eventually 'get it'.

 

I think that I may even write a guide on this, that gives step-by-step instructions on creating using, and manipulating arrays, so that others who think in the same manner as I do, will understand, because this is extremely useful.

 

The information on var scope has also been useful, and I now plan ahead for this. (Example: Hard-coding strings, will include the strings at the local level of the functions, but can use a global array, so I can define the columns/rows at a local level, that point to a global array.) My greatest thanks. to al of you, again!





Also tagged with one or more of these keywords: arrays, global, template

1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users