• Advertisement
Sign in to follow this  

Code Eval.

This topic is 2776 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was writing a method last night and discussing it in an irc channel.

When I mentioned that I had to do some typecasting, one of the members of the channel said it sounded as if the code was not well-written. The method "interact" is supposed to call "react" of another Entity. (Due to the extreme confusion this is creating for me, I will most likely remove "react" but that does not change this discussion). The point of this is that one Entity will initiate a response from another and it will vary depending on the initiating Entity and the target Entity.

Here is MY code where the method is being used:


using gfx

//The Player is the basic Entity manipulated by the user

class Player : Entity, Movable
{
...

override Void interactWith(Entity e, Graphics g)
{
if (e.typeof() == Enemy#)
{
Enemy enemy := (Enemy) e
enemy.health -= 10
enemy.react(this, g)
}
else if (e.typeof() == Stone#)
{
Stone stone := (Stone) e
stone.react(this, g)
}
else
{
}

}
...

}




It works the way it is currently. However, I was recommended to use this revised code snippet for better polymorphism. My concern is that I do not believe this will work as I intend and it's obvious by reviewing the code that it would not even have the same effect.



class Entity
{
...
Void interract(Whatever o, Graphics g)
{
this.reactto(o, g)
}
...
}

class Enemy : Entity
{
...
override Void interract(Whatever o)
{
this.health -= 10
this.reactto(o)
}
...
}

class Stone : Entity
{
...
}

override Void interactWith(Entity e, Graphics g)
{
e.interact(this, g)
}




I want my code to be maintainable and it does follow polymorphism to some extent. However, is the current state of my code bad because of the typecasting? I think the respondent may have had some confusion as to what I'm meaning to do here, and I'm not sure it'd be possible without typecasting to get the multidirectional interaction.

Any comments are welcome.

[Edited by - Fuji on July 18, 2010 1:52:42 PM]

Share this post


Link to post
Share on other sites
Advertisement
Which language is this?

Either way, querying for type is bad practice in all languages, except those that do not support polymorphic function calls.

The actual issue here is whether multiple dispatch is supported.

Share this post


Link to post
Share on other sites
I'm sure polymorphic function calls are supported but I don't see a proper way to manage this system doing so.

Share this post


Link to post
Share on other sites
It looks like Pascal or something.

Here is a C++ example of how you can use virtual functions to provide different implementations for different entities


#include <iostream>
using namespace std;

class Entity
{
public:

Entity(int health, int damage) : health(health), damage(damage) {}

virtual void attack(Entity& e) = 0;

int health;
int damage;
};

class Player : public Entity
{
public:

Player() : Entity(10, 1) {}

virtual void attack(Entity& e)
{
e.health -= damage;
}
};

class Stone : public Entity
{
public:

Stone() : Entity(20, 0) {}

virtual void attack(Entity& e)
{
// Stone doesn't know how to attack. doing nothing...
}
};

int main()
{
Player player;
Stone stone;

cout << "Player health " << player.health << endl << "Stone health " << stone.health << endl;

cout << "Player attacks stone" << endl;
player.attack(stone);
cout << "Player health " << player.health << endl << "Stone health " << stone.health << endl;

cout << "Stone attacks player" << endl;
stone.attack(player);
cout << "Player health " << player.health << endl << "Stone health " << stone.health << endl;
}



Telling the stone to react from the interact function (or the attack function in my case) is not a good idea IMO. Rather I would have a list of enemies and interate through this list each game loop cycle. Something like

foreach(Enemy e in enemy_list)
{
if(!e.list_of_targets.empty())
{
Entity target = e.list_of_targets[0];
e.attack(target);
}
}


This might not be what you had in mind but its a start.
Personally I would not give the Entity class a interact/attack function. It doesn't make sense to me that all entities can interact or attack.

Maybe something like this:

class Entity { ... }
class Creature : public Entity { ... }
class Item : public Entity { ... }


The Creature class would get the attack function but not the Item class.
I leave it to you to decide if a stone is a creature, item or something else.

Share this post


Link to post
Share on other sites
Well, the current Entity class encompasses the interact and react methods for the sake of a player interacting with a stone will display text, a player interacting with an enemy will cause the enemy to take damage, an enemy reacting with a player will cause damage to the player, and so on.


using gfx

//The Entity is the core class which most other classes will be based off
//It declares the basic functionality everything should have

//Get rid of either react or interact since both aren't needed

abstract class Entity
{
Int x
{
get { return &x }
set { &x = it }
}

Int y
{
get { return &y }
set { &y = it }
}

Rect rect
{
get { return &rect }
set { &rect = it }
}

Brush brush
{
get { return &brush }
set { &brush = it }
}

new make(|This|? f := null) { f?.call(this) }

virtual Void init(Graphics g) { }

virtual Void render(Graphics g) { }

virtual Void update(Graphics g) { }

virtual Void act() { }

virtual Void react(Entity e, Graphics g) { }

virtual Void interactWith(Entity e, Graphics g)
{
//e.react(g)
}

}




As such, I can not implement the health into every entity and the interact and react methods have to be somewhat ambiguous. The stone is simply a map item that will block the player's movement but it can still be examined.

I definitely could expand the chain of inheritance for sake of reusability.

The language is Fantom http://fantom.org/

Share this post


Link to post
Share on other sites
Quote:
Original post by Fuji
Well, the current Entity class encompasses the interact and react methods for the sake of a player interacting with a stone will display text, a player interacting with an enemy will cause the enemy to take damage, an enemy reacting with a player will cause damage to the player, and so on.


You need to determine if language supports Multiple Dispatch. If yes, then it's trivial, otherwise it requires workarounds, such as those in C++.

Share this post


Link to post
Share on other sites
Quote:

I can not implement the health into every entity and the interact and react methods have to be somewhat ambiguous

I see

Share this post


Link to post
Share on other sites
Multiple dispatch is not supported. I'll have to look into how to resolve the issue by mocking said behavior.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement