Types yet again again again

Blitz3D Forums/Blitz3D Beginners Area/Types yet again again again

_PJ_(Posted 2009) [#1]
If I have a 'type' within another type's field, is there any means to associate other instances of this secondary type to the primary?

I know this can be achieved with a separate field which contains a value which can identify the first type, but this would be a slower process with large numbers of instances.

To explain a little more clearly:
Imagine the setup:
Const GENDER_MALE=1
Const GENDER_FEMALE=0

Const ANIMAL_DOG=0
Const ANIMAL_FISH=1
Const ANIMAL_CAT=2
Const ANIMAL_SPIDER=3
Const ANIMAL_RABBIT=4
Const ANIMAL_TYRANNOSAUR=5

Type owner
	Field Name$
	Field Gender
	Field pets.pet
End Type

Type Pet
	Field name$
	Field animal.animals
End Type

Type animals
	Field animaltype
	Field name$
	Field legs
End Type

JohnOwner.Owner = New Owner
JohnOwner\Name$="John Smith"
JohnOwner\Gender=GENDER_MALE

JohnOwner\Pets.Pet= New Pet
JohnOwner\Pets\Name$="Kittie"

JohnOwner\Pets\animal.animals=New animals
JohnOwner\Pets\animal\animaltype=ANIMAL_CAT
JohnOwner\Pets\animal\name$="Siamese"
JohnOwner\Pets\animal\legs = 4


But what if John has more than one pet?
JohnOwner\Pets.Pet= New Pet
JohnOwner\Pets\Name$="Spot"

JohnOwner\Pets\animal.animals=New animals
JohnOwner\Pets\animal\animaltype=ANIMAL_DOG
JohnOwner\Pets\animal\name$="Sheepdog"
JohnOwner\Pets\animal\legs = 4

Just overwrites the 'Cat' info.

Is therwe a way to add a "sheepdog" as John's pet without either:

a) Making a 2ndary "John" instance of Owner
b) Adding a new field to "Pet" to identify the Owner.Owner as "John"?


Warner(Posted 2009) [#2]
There are several ways to solve this. I would use this construction:

The child objects are linked together by adding a field that points to the next object in the series.


_Skully(Posted 2009) [#3]
Actually I would go with a linked list...

Type TOwner
     Field name$
     Field firstPet.TPet
End type

Type TPet
     Field name$
     Field NextPet.TPet
     Field Owner.TOwner
End Type


This way its fast and easy to get all the pets that an owner owns and all the pets know who they below to.


Warner(Posted 2009) [#4]
Haha .. that is a good idea indeed. It also works in Java, C++ and BMax.


_PJ_(Posted 2009) [#5]
Thanks guys, so it seems either way will still require iterating through to find common references,
i.e. Warner's "For o.TOwner = Each TOwner" and Skully's use of the Owner.Owner field.

There's no means of having these links 'internally'?

The reason for my asking is because the situation may arise that (continnuing the owner/pet example) I may have around 50 owners, each with a few hundred pets, many of these pets may have the same names and be the same type of creature.

I am unsure as yet whether to make use of parent/child entity relationships as certain details pertaining to the pets may refer to child entities of another sort :S


Warner(Posted 2009) [#6]
No, I think you are misreading the code. The line 'For o.TOwner = Each TOwner' is just used in the example. It isn't used to find out which pets belong to who.
Instead, this part:
                p.TPet = o\firstPet
		While p <> Null
		
			Print "  Pet = " + p\name$
			p = p\nextPet
			
		Wend 

Iterates through all pets that belong to 'o'.

That was the whole idea: to create something along the lines of this:
(Imaginary code)
For p.Pet = Each Pet In o.Owner
  print p\Name$ + " belongs to " + o\Name$
Next

Google a bit for linked list. Here is a picture to illustrate how they work:



_Skully(Posted 2009) [#7]
Woops! I forgot a critical element...

Type TOwner
     Field name$
     Field firstPet.TPet
End type

Type TPet
     Field name$
     Field NextPet.TPet
     Field PrevPet.TPet
     Field Owner.TOwner
End Type

Function AddTPet(o.TOwner,name$)
     p.Tpet=o\FirstPet
     if p<>null then
        repeat
           if p\NextPet=null then
              ; initialize TPet code
              p\NextPet=new TPet
              p\NextPet\name=name
              p\NextPet\Owner=o
              Exit
           End If
        until o\NextPet=null
     else
        o\FirstPet=new TPet
        o\FirstPet\name=name
        o\FirstPet\Owner=o
     End if
End Function

Function DeleteTPet(p.TPet)
     If p\PrevPet<>null then 
        p\PrevPet\NextPet=p\NextPet
        If p\NextPet<>null then
          p\NextPet\PrevPet=p\PrevPet
        End If
     End If
     Delete p
End function



Warner(Posted 2009) [#8]
Hey, has anybody seen my cat? He was here two seconds ago ..


GIB3D(Posted 2009) [#9]
Is this your cat? *Hands over road kill*


_PJ_(Posted 2009) [#10]
Thanks, sorry Warner yes, I did misunderstand, thanks for the info though, I can follow that no problem.

Now I just need to consider whether to create a linked list instance and add to it as new "pets" are added to "owners" or whether to only populate it when it is required and tghus take the time then to retrieve all the data.


Ross C(Posted 2009) [#11]
I know exactly what you mean Malice. It would be handy if you could create a type list, just for that object. Kind of like a second dimension in an array, that is only accessed by the one first slot.

Something like:

Type owner
   field name$
   Type pet
      field name$
   End Type
End type


Then do something like:

For p.owner.pet = each owner.pet
   ;loop through each owners lists of pets
next

or

temp.owner = first owner
for temp.owner.pet = each pet
   ; loop through the FIRST owners pets
next


That would be handy :)


Hotshot2005(Posted 2009) [#12]
I didnt know blitz 3D can do this

Type owner
   field name$
   Type pet
      field name$
   End Type
End type

[


Warner(Posted 2009) [#13]
Is this your cat? *Hands over road kill*
Nope :/


_Skully(Posted 2009) [#14]
HotShot2005, it can't.


Ross C(Posted 2009) [#15]
Yeah, sorry. I was meaning, i wish you could :)


_PJ_(Posted 2009) [#16]
I'm sure one of the pet monkeys talks...


John Blackledge(Posted 2009) [#17]
But you _can_ do this, to get types within type.
(Substitute your own variables for 100)
Type Jpathpoint
	Field x,z
End Type

Type Jseq
	Field startframe
	Field endframe
End Type

Type JChar
	Field label$
	Field seq.Jseq[100]
	Field pathpoint.Jpathpoint[100]
End Type

Dim char.JChar(100)

For z = 0 To nNumChars
	char(z) = New JChar
	For cnt = 0 To 100
		char(z)\seq.Jseq[cnt] = New Jseq
	Next
	For cnt = 0 To 100
		char(z)\pathpoint.Jpathpoint[cnt] = New Jpathpoint
	Next
Next

Access using something like:
char(num)\pathpoint[p]\x = 10


Matty(Posted 2009) [#18]
Or you can do it using a bank, and storing in the bank a list of type handles, then simply iterate through the bank one int at a time to get the handles of all the pets:

IE
type person

field petbank

end type

type pet

field petname

end type 

;now for a specific person with a bunch of pets attached do this:
;we'll call our person instance 'human'
if human\petbank<>0 then 
     ;human has a bank containing all their pets
     for offset=0 to banksize(human\petbank)-4 step 4
               mypet.pet=object.pet(peekint(human\petbank,offset))
               if mypet.pet<>null  then
                       ;this is one of my many pets
              endif 
     next 

endif 





Ross C(Posted 2009) [#19]
SO, your basically just using object handle? I do that with arrays. For simplicity sake, it would be easier to have a linked list, directly connected with another, that no other linked list object could access. I know you can do this with types and arrays, however i didn't realise you could go so deep with it :) Thanks John.

I guess i'm woried mainly about the memory requirements when you start using arrays for large projects.


_PJ_(Posted 2009) [#20]
Well John & Matty, I'm having a little trouble 'visualising' what's happening there. I'm still not 100% on how to use "Object" and "Handle" commands, though I figured they might feature in this somewhere.

Which is the "best" (i.e. most efficient) way to to do this considering some 50 people and over a hundred 'pets' each?

As for the Banks... Aren;t banks actually gonna be less memory than a separate Type, considring the bank would just be the 'raw' int's rather than excess info concerning the types and fields etc. ?


Yasha(Posted 2009) [#21]
With fifty people and a hundred pets each... use array fields in the owner type. Five or ten thousand "wasted" array spaces isn't going to be a noticeable memory hit, and access will be an order of magnitude (literally) faster than using banks or linked-lists - much more efficient if performance is your priority.


John Blackledge(Posted 2009) [#22]
Totally agree with Yasha, so long as you are storing raw info/flags, and not whole meshes, then arrays are incredibly fast.


_PJ_(Posted 2009) [#23]
Okay thanks for that.

The main reason I approached this with Types rather than arrays was because the number of 'pets' and 'owners' are completely variable but I reckon I can set a top limit and if the 'wasted' array space isn't likely to be an issue, that's all good.