Types, room.chair

Blitz3D Forums/Blitz3D Beginners Area/Types, room.chair

boomboom(Posted 2007) [#1]
Right, I have been programmign in Blitz3D for years now, and use types quite often. I understand how to use them, but always had a question, and maybe I am missing something.

In example used in the doc's is:

room.chair = New chair

What is the first 'chair' for? Why didn't mark make blitz do:

room = New chair

being, make a new type of chair in the room list.


chwaga(Posted 2007) [#2]
yeah, I don't get that either lol


Terry B.(Posted 2007) [#3]
Because that would declaring "room" as an interger varible and then assigning the "new chair" handle to it.... which would be a MAV..

I think ;)


boomboom(Posted 2007) [#4]
So I guess:

room$ is a variable that uses the format of a string
room.chair is a variable that uses the format of a 'chair'?

the '.chair' replacing the '$'


Floyd(Posted 2007) [#5]
the '.chair' replacing the '$'

That's it exactly.

There are three built-in variable types ( integer, float, string ) and user defined ones, such as chair. A variable's type is determined when it is explicitly declared, with Global or Local, or whenever the compiler first sees the variable in your code.

So if the variable room, of type chair, has been declared or already appeared earlier in the code you can simply say

room = New chair

And as long as I'm in lecture mode, the return type of a function is determined in the same way:

Function f#( ) ; will return a float

Function g.chair( ) ; will return a chair, whatever that is.


boomboom(Posted 2007) [#6]
Ah, so I an do it the way I want by first declaring the room as a variable type 'chair'

Type chair
	Field Name$
	Field Height
End Type

Global room.chair

room = New chair
room\Name = "Nice Chair"

room = New chair
room\Name = "Bad Chair"

For room = Each chair
	Print room\Name
Next

WaitKey()


I guess its abit easyer for readbility to keep the .chair in there all the time, so you can remember its a type.

So if I use a function and return whole type entry, how do I then access the fields in that returned entry?


H&K(Posted 2007) [#7]
I guess its abit easyer for readbility to keep the .chair in there all the time, so you can remember its a type
Only because for some unknown reason youve called a Chair "Room". If you had called it "GlobalChair" or "AChair" or "MyChair" or "LocalChair" or heaven forbid "Chair" it would be a lot better.

Calling it something not Chair related is bad enough, but to call it something that might contain Chairs is stupid


boomboom(Posted 2007) [#8]
Its called 'room' becuase thats the example given in the official docs and I didn't want to add to the confusion. Which also makes sence, as its keeping a collection of 'chairs' in a list called 'room'


PowerPC603(Posted 2007) [#9]

So if I use a function and return whole type entry, how do I then access the fields in that returned entry?



Type chair
	Field Name$
	Field Height
End Type

Global room.chair

; Create a new chair type-instance, set it's name and return it to the variable "room"
room = CreateChair("Nice chair")
room = CreateChair("Bad chair")

For room = Each chair
	Print room\Name
Next

WaitKey()


Function CreateChair.chair(Name$)
	Local a.chair = New chair
	a\Name=Name$
	Return a
End Function


Here the creation of a chair type-instance and settings it's name is done within the function CreateChair, which returns the chair as a type-instance and gives it to the variable "room".
Afterwards, you can access the room's fields the same way as if you had created the type-instance in the main code.


boomboom(Posted 2007) [#10]
Excellent. Is there anything else about types I should know? As I said I have used them for years, but nothing more as a simple in/out database.


big10p(Posted 2007) [#11]
Excellent. Is there anything else about types I should know?
Depends. I don't know what else you already know about them.

Er, you can have types within types - that can be pretty useful.


H&K(Posted 2007) [#12]
its keeping a collection of 'chairs' in a list called 'room'
Hence Chairs[] should be a field of Room, and not that a chair should be called Room

Its called 'room' becuase thats the example given in the official docs
Then it is one of the things that was possible adding to your confusion about types. It a really really stupid way to name an instance of "Chair", because as you have just shown it confusing the issue between "Is A", and "Contains A".

ARoom may Conatian A Chair, and as such any Type TRoom can have fields of lists of Chairs or Arrays of chairs, or pointers to Banks of chair, in short in may conatin Chairs.

A Chair on the other hand Is Not A room, it is in no way similar to a room (Cept they both might have fleas in them), and shouldnt be called A room at all


boomboom(Posted 2007) [#13]
So how do you use types in types, and what use / benifit do they have?


tonyg(Posted 2007) [#14]
Its a bit like Inheritance.
Imagine you have a type called SpaceShip.
Type Spaceship
  field name$
  field topspeed%
end type

All Spaceships will have these attributes but might also have some other specific to themself.
For instance, your CargoShip might have a 'Cargo_hold' attribute when your Fighter might not.
You *could* give the Fighter a Cargo_hold value of 0.
Alternatively you can create a
Type CargoShip
  field basic_cargo.ships
  field cargo_hold
end type
type fighter
 field basic_fighter.ships
 field missiles%
end type.

Your Fighter and your CargoShips now only have the ir
specific attributes PLUS the basic attributes.
This is a small example but imagine if EVERY ship had to have a field for EVERY possible attribute.
In additiom, changing the base structure automatically gets updated to each ship type.


boomboom(Posted 2007) [#15]
how would I put data and get data back from the fighters name$ for example?

Would there be any additional things in code, or would it just count it as another field?


tonyg(Posted 2007) [#16]
You use myfighter.basic_fighter.name.


big10p(Posted 2007) [#17]
That would be myfighter\basic_fighter\name in blitz3D. ;)


tonyg(Posted 2007) [#18]
Ooops. You're right. It's been too long.


Jasu(Posted 2007) [#19]
I have used inheritance alot in my current project and I couldn't emphisize how important types in types are. Especially when the game is very dynamic. Here's one example of my type structure

Player   Ship
   |      |
  PlayersShip   Weapon
       |          |
        \        /
       WeaponMount
           |
       WeaponBullet


For example the WeaponBullet object has a field Parent.WeaponMount, WeaponMount has a field Parent.Weapon and Owner.PlayersShip, PlayerShip has fields Parent.Ship and Owner.Player . So when going through the bullets, to find out which Player shot this bullet, I code Shooter.Player=This\Parent\Owner\Owner . Why have PlayerShip and Ship as different types? Say the Ship type has attributes maxShields, mass, maxSpeed etc. Those fields are static information that does not change for this ship type. So the PlayerShip type has fields ShieldCharge etc. which is dynamic information. Always separate static and dynamic information to types of their own. You save memory and have some strictness in your code.

But what about going downwards in the hierarchy? There are two options. Let's think the PlayerShip can have several WeaponMounts. This can be done by having a field in PlayerShip
WeaponMounts.WeaponMount[7]
Which is a collection of pointers to WeaponMounts this PlayerShip has. This of course restricts the amount of weapons to eight. What about limitless amount? Object chain!
Type PlayerShip
   Field Parent.Ship
   Field Owner.Player
   Field PosX#
   Field PosY#
   Field WeaponMounts.WPChain
End Type

Type WeaponMount
   Field Parent.Weapon
   Field Owner.PlayerShip
   Field FireCoolOff%
End Type

Type WPChain
   Field Obj.WeaponMount
   Field NextWP.WPChain
EndType

P1.PlayerShip = New PlayerShip

W1.WeaponMount = New WeaponMount
W1C.WPChain = New WPChain
W1C\Obj = W1
P1\WeaponMounts = W1C

W2.WeaponMount = New WeaponMount
W2C.WPChain = New WPChain
W2C\Obj = W2
W1C\NextWP = W2C

Now going through the weapons of certain PlayerShip is easy.
Local WPC.WPChain = P1\WeaponMounts
While WPC<>null
   ; do what you want with WPC\Obj
   WPC = WPC\NextWP
Wend

I could go on and on about this.


blade007(Posted 2007) [#20]
i still dont understand how to use types inside of types. ahhh headache!


boomboom(Posted 2007) [#21]
Hey, say I have 3 space ships, and each ship has 5 guns (gun information is stored as a child type of the main parent space ship type).

How do I retrieve gun information only for the second space ship? When I using something like:

for P1.PlayerShip = Each PlayerShip
    Select P1\ShipNumber
      Case 2
         for P1\WeaponMounts.WeaponMount = Each WeaponMount
            *PLAYER 2'S GUNS ONLY*
         Next
    End Select
Next


But it brings back info for all the weaponmount child types not just ones on P1.

I see in Jasu's example he doesn't use the for/next loop, but instead stores the next weapon in the sequence and loop through 'manually'. But wouldn't that break if I deleted one of the middle ones and break the chain?

Whats the best way to do this?


Who was John Galt?(Posted 2007) [#22]
You're confusing the issue talking about 'just ones on P1'. P1 is the loop variable so takes on the value of all ships over the loops.

The reason you are getting all weapon mounts is that you are using each, which means 'loop through every weapon mount type'. So youre logic is saying 'find ship 2, then loop through every weapon mount, regardless of who it belongs to'.

The trouble is B3D has only 1 list for each type.. ideally you would like a separate list of weaponmounts belonging to each ship, right?

There are a few ways round this.
1)Each weapon mount has a field identifying the ship it belongs to.
2)Create separate weapon mount types, WeaponMounbt1, WeaponMount2 etc, one for each ship, thereby giving you more than 1 list.
3)Create arrays of weapon mounts for each ship, which store only the weapon mounts on that ship.
4)Implement your own lists enabling you to have 1 per ship.

The inherent '1 list per type' in B3D makes basic stuff simpler, but you're hitting the limitations of the language.


boomboom(Posted 2007) [#23]
ah, I guess this is the reasoning behind BlitzMax's decision not to automatically put things in lists? So you can have multiple user defined lists.

I think I will go with Fix number 1 please :)


Who was John Galt?(Posted 2007) [#24]
I guess this is the reasoning behind BlitzMax's decision not to automatically put things in lists?
I guess you're correct. I was tempted to put '5)Get BlitzMax' in my previous post, but I didn't want to go off topic!


boomboom(Posted 2007) [#25]
:)


boomboom(Posted 2008) [#26]
So if you can't retrieve a type inside a type, whats the point in using types within types? You might as well just keep them seperate and link them together with a pointer field?

Edit: *Click* that magical thing just happened when I finally realised the answer....there is no spoon! :)


boomboom(Posted 2008) [#27]
It that playership example Jasu posted really the only way to retrieve types in a type? It essentially involved each weapon manually linking to the next one, if the chain is broken, such as a weapon is removed, then all the links in all the weapons need updating in the chain (which might be hard to find as there no longer linked)

It just seems there should be an easyer way?


Stevie G(Posted 2008) [#28]
There are simpler, less dynamic ways like using a type array within a type. For example ..

const MaxWeapons = 5

type Weapon
field Blah
field Blah2
end type

Type Ship
field Mesh
field Blah
field Weapon.Weapon[ MaxWeapons-1 ]
End type

It really depends on how complex you need your ship / weapon type structures to be. How does your game work in terms of the weapons? Is there a finite number of weapon slots? When and how do they get removed? When removed do you default to the next avalable weapon? Do you always have at least one weapon?

Etc ..


Ross C(Posted 2008) [#29]
Remember OBJECT and HANDLE commands.


Jasu(Posted 2008) [#30]
Yes, use blitz arrays within a type if the amount of child types is finite. For 'infinite' type lists, the pointer chain is the only way to go.

I hope you didn't misunderstand what I mean about these pointer chains. If you, say, remove a weapon object, it doesn't break the chain. It's just that one of the objects in the weapons chain is pointing at null. The weapons and the list of weapons are completely different types.

Deleting objects from the pointer chain is a bit difficult (link of the last object has to be changed before deleting). As I was implementing this into my game, I noticed that simply deleting the whole list and recreating it from scratch was faster than modifying it. It of course depends hugely on what are you using it for.