Originally Posted by 3run
Switching from while to for loop won't indeed have any impact on frame rate.

As far as I have read, compilers do normally compile both instructions to the very same thing.

Originally Posted by Dooley
Do you have any general tips on reducing function complexity?

One thing you can try is to replace local variables of actions by entity skills. Acknex do restore and save actions stack memory each frame. It has a significant impact on execution when there are a lot. Entity skills are slower to read and write, so it is not a fire-written law but something to take into account in reference to variables usage. I did a messurement of the impact of 'wait' and stack size in my oldy computer some time ago: https://opserver.de/ubb7/ubbthreads.php?ubb=showflat&Number=474652#Post474652

Recursively accesing array members by its index is a little waste of resurces that can be avoided by getting the proper pointer. I mean:
Code
var array[100];

// acces array members by its index
int i = 0;
for(; i<100; ++i)
   array[i] = random(1); // it performs an addition each loop in order to access the array member: *(array + i) = ... 

// faster approach
var *ptr = array;
var *ptrLast = ptr + 100;
for(; ptr<ptrLast; ++ptr)
   *ptr = random(1); // No extra additions. The more accesses to array members, the more additions it avoids.


The use of var type as indexes on arrays also have a little penalty since the program have to cast them to long type. It is just a 10 bits right shift, but you know, dunes grow grain by grain.

I will always recomend the use of function pointers on complex state machines. Function pointers let you atomize the execution and avoid the whole switch/case block commonly used to build state machines. I do normally set the function scheduler and state machines into the same system. Something like the following:
Code
#include <acknex.h>
#include <default.c>

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

#define ITEMS_MAX              1000

typedef struct SCHEDULER_ITEM
{
	void *object;
	void *state(void *item);
	void remover(void *item);
} SCHEDULER_ITEM;

SCHEDULER_ITEM items[ITEMS_MAX];
int itemCount = 0;

SCHEDULER_ITEM *itemAdd(void* object, void *remover, void *state)
{
	SCHEDULER_ITEM *item = items + itemCount;
	itemCount += 1;
	
	item->object = object;
	item->state = state;
	item->remover = remover;
	
	return item;
}

void itemRemoveAll()
{
	SCHEDULER_ITEM *item = items;
	SCHEDULER_ITEM *itemLast = item + itemCount;
	for(; item < itemLast; ++item)
		item->remover(item->object);
	itemCount = 0;
}

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

// Prototypes
void *stMoveUp(ENTITY *ent);

// States
void *stWaitDown(ENTITY *ent)
{
	ent->skill2 += time_step;
	if(ent->skill2 > ent->skill1)
	{
		ent->skill4 += 1;
		if(ent->skill4 > ent->skill3)
		{
			return NULL;
		}
		
		ent->skill1 = random(200);
		ent->skill2 = 0;
		
		return stMoveUp;
	}
	
	return stWaitDown;
}

void *stMoveDown(ENTITY *ent)
{
	ent->z -= time_step * 10;
	
	if(ent->z < ent->skill1)
	{
		ent->skill1 = 4 + random(16);
		ent->skill2 = 0;
		return stWaitDown;
	}
	
	return stMoveDown;
}

void *stWaitOnTop(ENTITY *ent)
{
	ent->skill2 += time_step;
	
	if(ent->skill2 > ent->skill1)
	{
		ent->skill1 = -random(200);
		ent->skill2 = 0;
		
		return stMoveDown;
	}
	
	return stWaitOnTop;
}

void *stMoveUp(ENTITY *ent)
{
	ent->z += time_step * 10;
	
	if(ent->z > ent->skill1)
	{
		ent->skill1 = 4 + random(16);
		ent->skill2 = 0;
		return stWaitOnTop;
	}
	
	return stMoveUp;
}

void sphereCreate()
{
	if(itemCount > ITEMS_MAX - 1)
		return;
	ENTITY *ent = ent_create(SPHERE_MDL, vector(0, random(600) - 300, -random(200)), NULL);
	ent->skill1 = random(200); // limit
	ent->skill2 = 0; // limit counter
	ent->skill3 = 1 + random(4); // Count of loops
	ent->skill4 = 0; // loop counter
	
	itemAdd(ent, ent_remove, stMoveUp);
}

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

void scheduler()
{
	int index = 0;
	SCHEDULER_ITEM *item = items;
	for(; index < itemCount; ++index, ++item)
	{
		item->state = item->state(item->object);
		if(item->state != NULL)
			continue;
		item->remover(item->object);
		itemCount -= 1;
		memcpy(item, items + itemCount, sizeof(SCHEDULER_ITEM)); // The fastest deletion but sorting gets broken.
		index -= 1;
		item -= 1;
	}
}

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

void createMultipleEntities()
{
	int i = 0;
	for(; i<ITEMS_MAX; i+=1)
		sphereCreate();
}

void main()
{
	max_entities = maxv(ITEMS_MAX, 5000);
	wait(3);
	level_load("");
	camera->x = -600;
	
	createMultipleEntities();
	
	on_esc = NULL;
	on_space = sphereCreate;
	
	while(!key_esc)
	{
		scheduler();
		wait(1);
	}
	
	itemRemoveAll();
	sys_exit(NULL);
}


Hope it helps...
Salud!