Array length

Started by MurrayL, Sat 27/08/2011 18:31:49

Previous topic - Next topic

MurrayL

Hi guys,

Sorry if this has been asked before; it's a pretty simple question but the forum search function has fallen over.

How can I find out the length of an array in AGS?
Normally I'd expect an array.length() function, but I'm not seeing anything like that in the editor prompts or help files.

DoorKnobHandle

There's no way to do this for static arrays. At some point you declare the array (int array[20]) and in there is the size of the array. Do this:

Code: ags

#define ARRAY_SIZE 20

int array[ARRAY_SIZE];

// now you have the size of the array in AFFARY_SIZE

MurrayL

Hmm, I thought that might be the case  :-\

I'd rather use a dynamic array if possible, but I just read in another topic that you can't get their length through script.

No matter; thanks for the help!

DoorKnobHandle

Yeah, it's the same deal for dynamic arrays unfortunately.

We could really use a std::vector like dynamic array class that would take care of all this stuff - not only for in-build types. Doesn't exist yet though to the best of my knowledge.

MurrayL

There's support for multi-dimensional arrays, though, right?  ???

I sense impending disappointment.

monkey0506

#5
If by "multi-dimensional arrays" you mean "single-dimension arrays padded to the total necessary size to accommodate the same number of elements", then yes, AGS supports that. :=

Code: ags
int array[];
int array_dims[];
int array_dim_count = 3;
int array_size;

function game_start()
{
  array_dims = new int[array_dim_count];
  array_dims[0] = 2;
  array_dims[1] = 3;
  array_dims[2] = 4;
  int i = 0;
  array_size = 1;
  while (i < array_dim_count)
  {
    array_size = (array_size * array_dims[i]);
    i++;
  }
  array = new int[array_size];
}

int get_array_index(int indices[])
{
  int index = 0;
  int i = 0;
  while (i < array_dim_count)
  {
    index += indices[i];
    if ((i + 1) < array_dim_count) index = (index * array_dims[i + 1]);
    i++;
  }
  return index;
}

int get_array_value(int indices[])
{
  int index = get_array_index(indices);
  return array[index];
}

void set_array_value(int indices[], int value)
{
  int index = get_array_index(indices);
  array[index] = value;
}


This is based on the formula:
int array[A][B][C]; // int array[A * B * C];
array[a][b][c] = x; // array[(((a * B) + b) * C) + c] = 5;
You multiply the index of each dimension by the maximum value of the following dimension and add in the index of the following dimension.

Resizing dynamic arrays is also relatively simple even though there's nothing built-in. Presumably a built-in method would be more efficient, but this is functional:

Code: ags
int array[];
int array_size;

void resize_array(int size)
{
  if (!array_size)
  {
    array = new int[size];
    array_size = size;
    return;
  }
  int buffer[] = new int[size];
  int i = 0;
  while ((i < size) && (i < array_size))
  {
    buffer[i] = array[i];
    i++;
  }
  array = buffer;
  array_size = size;
}

MurrayL

Forgive me for being an idiot; I must continue my reign of terror.

I've now got something resembling what I want using an array of Structs. Unfortunately I need a GUI control to reference it in its OnClick event, and the array of Structs is initialised within a room rather than in the global script.

If I move the initialisation of the Struct to the globalscript, the room can't access it ('undefined token').
Is there something I'm missing with regards to creating a globally accessible array? I tried putting it at the very top of the globalscript.asc but to no avail.

Sample (just using test data until I get it all working):

Code: ags

// room script file
struct EmailMessage
{
  int day;
  int tier;
  String keywords;
  String fullText;
};

EmailMessage emailMessages[36];

function room_FirstLoad()
{
  //Day 1 Tier 1
  emailMessages[0].day=1;
  emailMessages[0].tier=1;
  emailMessages[0].keywords="1 1 1";
  emailMessages[0].fullText="Day 1[Tier 1[Message 1";
  emailMessages[1].day=1;
  emailMessages[1].tier=1;
  emailMessages[1].keywords="1 1 2";
  emailMessages[1].fullText="Day 1[Tier 1[Message 2";
  emailMessages[2].day=1;
  emailMessages[2].tier=1;
  emailMessages[2].keywords="1 1 3";
  emailMessages[2].fullText="Day 1[Tier 1[Message 3";
  
  //Day 1 Tier 2
  emailMessages[3].day=1;
  emailMessages[3].tier=2;
  emailMessages[3].keywords="1 2 1";
  emailMessages[3].fullText="Day 1[Tier 2[Message 1";
  emailMessages[4].day=1;
  emailMessages[4].tier=2;
  emailMessages[4].keywords="1 2 2";
  emailMessages[4].fullText="Day 1[Tier 2[Message 2";
  emailMessages[5].day=1;
  emailMessages[5].tier=2;
  emailMessages[5].keywords="1 2 3";
  emailMessages[5].fullText="Day 1[Tier 2[Message 3";
  
  //Day 1 Tier 3
  emailMessages[6].day=1;
  emailMessages[6].tier=3;
  emailMessages[6].keywords="1 3 1";
  emailMessages[6].fullText="Day 1[Tier 3[Message 1";
  emailMessages[7].day=1;
  emailMessages[7].tier=3;
  emailMessages[7].keywords="1 3 2";
  emailMessages[7].fullText="Day 1[Tier 3[Message 2";
  emailMessages[8].day=1;
  emailMessages[8].tier=3;
  emailMessages[8].keywords="1 3 3";
  emailMessages[8].fullText="Day 1[Tier 3[Message 3";
}


I need functions in both room and global scripts to be able to read/write to emailMessages freely.

MurrayL

Sorry to double-post; that's what I get for not reading the documentation properly.

Just found the import and export keywords and (after some fiddling) I think I have it working.

As a curiosity, I currently define the struct at the top of globalscript.asc and room1.asc. When I tried to export/import the struct, AGS threw a wobbly; is this intended behaviour, or did I get my syntax in a muddle?

Khris

Just move the struct definition to the header.

SMF spam blocked by CleanTalk