Using banks

Blitz3D Forums/Blitz3D Programming/Using banks

PowerPC603(Posted 2004) [#1]
Hi there,

Is it possible to use a bank to store pointers to type-instances?

I'm working on a spacegame and each space-sector can have a different amount of spacestations in it.

Right now I'm using an array of types (1 dimension) to store the pointers to the Sector-type-instances and another array (2 dimensions) to hold all pointers to all spacestation type-instances.

Type Sector
	Field Name$
	Field ...
End Type

Type Station
	Field Name$
	Field ...
End Type

ArraySectors.Sector(5)
ArrayStations.Station(5, 10)


For the second array: the first dimension holds the SectorNumber (5 Sectors), the second one holds the StationNumber (10 Stations per sector).
Actually 6 Sectors and 11 Stations, but I don't use index 0, because it's difficult as it is right now for me to keep things organised.

This code shows the current setup (only an example), because the arrays are redimmed to hold all data, which is stored in a textfile (so the size of those arrays is based on the data in that file).

But when a sector (say sector 3) only has 1 station in it, then the array DOES have 10 indexes available (which are not used at all) for that sector.

When the universe is small (like in this example), then this will not be an issue for memory-usage, but when the universe has about 150 sectors and a maximum of 25 stations per sector, then it can lead to a lot of unused memory.
And not all sectors will have those 25 stations inside it.
The most populated sector will have 25 stations (as an example, don't know yet how many it will be eventually).

I tried to include another field in the Sector-type, which hold the pointer to a bank.

Type Sector
	Field Name$
	Field SectorList = CreateBank(0)
End Type


After that, I've tried to assign a new Station-type-instance to this bank (after resizing it), but I got a "Illegal Type Conversion" error.

So I wanted to have each Sector-type-instance have it's own bank, which would hold all pointers to all Station-type-instances in that sector.
This could work as a linked-list of Stations per sector.

It would be sort sort of private TList (like in BMax), but then with Banks.

Then no memory is wasted, as the bank would only be as big as needed to hold all pointers.


Is this possible?
If it is possible, how can I do this?


PowerPC603(Posted 2004) [#2]
It seems I'm able to convert an type-pointer to an int and store that:

Type Sector
	Field Name$
	Field SectorList
End Type

Type Station
	Field Name$
End Type

NewSector.Sector = New Sector
NewSector\SectorList = CreateBank(4)

PokeInt(NewSector\Sectorlist, 0, Int(New Station))
Print PeekInt(NewSector\SectorList, 0)

WaitKey()
End


Can this be reverted (convert an Int back to a pointer)?

When I try this before the Waitkey() statement:
NewStation.Station = PeekInt(NewSector\SectorList, 0)


I again get an "Illegal Type Conversion" error.


Techlord(Posted 2004) [#3]
Although I despise the Object/Handle Commands they may server your purpose well.
Type Sector
	Field Name$
	Field SectorList
End Type

Type Station
	Field Name$
End Type

NewSector.Sector = New Sector
NewSector\Name$="The Base"
NewSector\SectorList = CreateBank(4)

NewStation.Station=New Station
NewStation\Name$="Alpha 1"

PokeInt(NewSector\Sectorlist, 0, Handle(NewStation))
AStation.Station=Object.Station(PeekInt(NewSector\SectorList, 0))

Print AStation\Name$

WaitKey()
End


My approach would be different. I would use a Array of Types and add a Field ID to the Station Type. Theres a little more code, but, its faster and you have complete control over objects created.

Type Sector
	Field Name$
	Field SectorList
End Type

Type Station
	Field ID
	Field Name$
End Type

Dim StationID.Station(100) ;<-- array of types
Global Stations

NewSector.Sector = New Sector
NewSector\Name$="The Base"
NewSector\SectorList = CreateBank(4)

NewStation.Station=New Station
Stations=Stations+1
NewStation\ID=Stations
StationID(NewStation\ID)=NewStation
NewStation\Name$="Alpha 1"

PokeByte(NewSector\Sectorlist, 0, NewStation\ID)
AStation.Station=StationID(PeekByte(NewSector\SectorList, 0))

Print AStation\Name$

WaitKey()
End



PowerPC603(Posted 2004) [#4]
I will give your first idea a try (Object and Handle commands).

I've rewritten the entire load-routines for this datafile, so now only if a station really exists, the type-instance will be created, it's pointer gets put inside the array and the data is loaded into the type-instance.
This way only the 4 bytes (index of an array) are lost.

First I had lots of unused type-instances (dim the array and fill it with pointers to new type-instances).

Dim ArrayStations.Station(NumberOfSectors, MaxNumberOfStations)

For i = 1 To NumberOfSectors
	For j = 1 To MaxNumberOfStations
		ArrayStations(i, j) = New Station
	Next
Next


At first, a few unused 100Kb did matter.
Now, a few unused bytes won't matter, I think.

I'll give it a try and decide which approach will be best for the game (and easiest).


Rottbott(Posted 2004) [#5]
Object() and Handle() are really useful commands for a great number of things. You can even store the type handles in the entity name with NameEntity()/EntityName$().

I haven't read all of this, but why do you actually need to store all these type handles? Usually you only need a handle when you want to do something specific to one object, to update all of them you'd use For Each, and so on. The entity name trick usually removes the need for arrays indexing each type object.


PowerPC603(Posted 2004) [#6]
I'm using arrays to quickly pinpoint a specific type.

Let's say I've got 200 sectors and 20 stations per sector.
This is equal to 4000 type-instances.

Now, the player can only be in one sector of space at any given time (like Freelancer).

So, to loop through all stations in the sector where the player is located, I would only have to loop through all indexes of the array for that sector, instead of looping through all 4000 type-instances:

; this code print only the 20 stations inside the current sector
; where the player is located
For i = 1 To 20
	Print ArrayStations(CurrentSector%, i).Name$
Next


The var "CurrentSector%" holds the current sectornumber where the player is located.

Without using arrays (and need updating all stations inside the current sector), I would have to do something like this:
For CurrentStation.Station = Each Station
	If CurrentStation\BelongsToSector$ = SectorName$
		...
	EndIf
Next


Looping through all stations (where 99.5% of them (3980 out of the total 4000) don't need to be checked) is a bit overkill when only updating 1 sector.

But now I have succesfully converted my loading routines into BMax, using resizable arrays-of-types inside types.
No more trouble about unused array-indexes.

Now I have actually what I wanted, except a 3D module, to create an entire sector and fly through it, of course (which my B3D-version could do right now).

Now I can add stations to a sector, without having to know the maximum number of stations that exist inside a given sector (the most populated one) to firstly dim the array to the proper size, before loading data into it.

Each time a station is added now, the array-size is increased by 1 (the contents don't get lost in BMax) and the new station is added to the sector.