Undo/redo functionality with LinkedList<Action> implementation - c#

I am writing my own 'Rubik's cube' application. The main class Cube has 18 rotation methods:
RotateAxisXClockWise, RotateAxisXAntiClockWise
RotateAxisYClockWise, RotateAxisYAntiClockWise
RotateAxisZClockWise, RotateAxisZAntiClockWise
RotateUpperFaceClockWise, RotateUpperFaceAntiClockWise
RotateFrontFaceClockWise, RotateFrontFaceAntiClockWise
RotateRightFaceClockWise, RotateRightFaceAntiClockWise
RotateBackFaceClockWise, RotateBackFAceAntiClockWise
RotateLeftFaceClockWise, RotateLeftFaceAntiClockWise
RotateDownFaceClockWise, RotateDownFaceAntiClockWise
Yes, they could be joined in pairs with a parameter Direction (for example RotateFrontFace(Direction direction)) but for now this seems appropriately.
I would like to implement undo/redo functionality and because all methods have the same signature (no input parameters, void return type) they could be saved in a LinkedList data structure. So every time one of the rotation methods is called, it is added to the linked list.
This would work pretty well if we start on the beginning of the LinkedList (haven't tried it out yet though) and advance toward the end, so each rotation would be performed exactly as it was in the first place.
But what about undo? If I traverse the list from the end to the beginnig, then the opposite method should be called (for example instead of RotateFrontFaceClockWise, RotateFrontFaceAntiClockWise should be called). Any ideas how to implement this? Elegantly? :)

I would not use delegate references as the way to model the rotations, if one of the main purposes is to be able to perform redo/undo. I would consider creating a data-model for each rotation, and store a list of these rotation steps. Each step could then have it's own associated Redo/Undo delegate, which allows someone traversing the list (from either end) to understand what operations took place, and either repeat or reverse them.
One additional benefit of a data-oriented approach to model such transformations, is that it could potentially reduce the number of similar (but slightly different) versions of your RotateXXX( ) methods.
EDIT: Addressing the your question about what shape such a solution might take.
The simplest thing to do may be to store a Tuple<Action,Action> representing each pair of rotate/unrotate operations as paired delegates. However, I would consider using an explicit data structure that describes the rotation operation, perhaps eventually including things like a descriptive name, direction/face attributes, and so on. I would also change your RotateXXX methods so that they are static methods of Cube, and accept an instance of cube as a parameter. This would allow modeling the rotation operations externally to the instance of Cube.
public sealed class Rotation
{
private readonly Action<Cube> _RotateAction;
private readonly Action<Cube> _UnrotateAction; // used for undo or backtracking
private Rotation( Action<Cube> rotateAction, Action<Cube> unrotateAction )
{
_RotateAction = rotateAction;
_UnrotateAction = unrotateAction;
}
public void Rotate( Cube cube ) { _RotateAction( cube ); }
public void Unrotate( Cube cube ) { _Unrotate( cube ); }
public static readonly RotateFrontFaceClockswise =
new Rotation( Cube.RotateFrontFaceClockwise
Cube.RotateFrontFaceCounterClockwise );
public static readonly RotateFrontFaceCounterClockwise =
new Rotation( Cube.RotateFrontFaceCounterClockwise,
Cube.RotateFrontFaceClockwise );
public static readonly RotateLeftFaceClockwise =
new Rotation( Cube.RotateLeftFaceClockwise,
Cube.RotateLeftFaceCounterClockwise );
public static readonly RotateLeftFaceCounterClockwise =
new Rotation( Cube.RotateLeftFaceCounterClockwise,
Cube.RotateLeftFaceClockwise );
// etc..
}
// now we can keep track of the state changes of a cube using:
List<Rotation> cubeRotations = new List<Rotation>();
cubeRotations.Add( Rotation.RotateFrontFaceCounterClockwise );
cubeRotations.Add( Rotation.RotateBackFaceClockwise );
cubeRotations.Add( Rotation.RotateLeftFaceCounterClockwise );
// to apply the rotations to a cube, you simple walk through the data structure
// calling the Rotate( ) method on each:
Cube someCube = new Cube( ... )
foreach( Rotation r in cubeRotations )
{
r.Rotate( someCube );
}
// to undo these rotations you can walk the like in reverse:
foreach( Rotation r in cubeRotations.Reverse() )
{
r.Unrotate( someCube );
}

I know you wanted to avoid parameterizing your methods, but you're probably best off pursuing something along those lines:
enum Face
{
Top,
Bottom,
Left,
Right,
Front,
Back
}
enum Direction
{
Clockwise,
CounterClockwise
}
struct Rotation
{
public Face Face;
public Direction Direction;
}
LinkedList<Rotation> actions;
You can make a choice whether to push the direct or inverse action onto the list, but once you store the actions in this way, its very easy to write some quick switch statements to reverse an action as it gets removed from the list.
On a side note, consider replacing LinkedList with Stack, it will server you just as well and its suited for the purpose perfectly.
EDIT:
Noticed that I don't have support for the axis rotations in my enumerations, but I'm sure you could add them as additional entries in the Face enumeration (although you might want to rename it at that point)

18 methods seems like a lot to keep up with, especially when you consider implementing the undo/redo functionality. Have you considered using a single, more generic method? If you did so, you could store what was passed to that method in a very uniform manner, and easily perform the opposite actions. The opposite actions could be looked up from a dictionary.

Assuming you really want to stick to your model...
You could try by entering in the list every name of the method executed and then, with reflection, call the counter parts by iterating over the list. This assumes that your methods will have matching names (as you proposed).
You could also create a HybridDictionary into which you use the method names as the id and addressof the counter method as the value. And so when you iterate over the list you could have a delegate handle the method at the given value.

Related

How to define a method that makes assumptions about object state?

In our geometry library, we have a Polygon class, containing (amongst many others, of course) a method which checks if this polygon contains another polygon:
public bool Contains(Polygon other) {
//complex containment checking code goes here
}
Other important things to note are that the polygon is mutable, and that there is no way to be notified of when its shape changes.
Now, in one of our projects, we have a validation function, which checks for a huge number of polygons whether they are all contained within a single outer boundary.
Polygon boundary = ...;
foreach (var poly in _myMassiveListOfPolygons)
if (!boundary.Contains(poly))
//error handling code goes here
Profiling has determined this to be quite a bottleneck. Fortunately there is a way to vastly speed up the calculation. We know that the boundary polygon is always convex, so instead of using the general Contains method, we can write a specialized method that assumes the outer polygon is convex.
Initially I added something like this to the client code:
Func<Polygon, bool> containsFunc;
// Keep both options, in case my assumption about being always convex is wrong
if (boundary.IsConvex())
{
containsFunc = p => { ... }; //efficient code for convex boundary goes here
}
else
{
containsFunc = p => boundary.Contains(p);
}
foreach (var poly in _myMassiveListOfPolygons)
if (!containsFunc(poly))
//error handling code goes here
Joy all around! Performance has increased tenfold!
However, it doesn't seem right that the code for this alternative Contains method is located in the client project, where it can't be reused by others.
So I tried to move it to the Polygon class itself.
public bool Contains(Polygon other) {
if (this.IsConvex())
return ConvexContains(other);
else
return GenericContains(other);
}
private bool GenericContains(Polygon other) { ...}
private bool ConvexContains(Polygon other) { ...}
With this method, the client code returns back to the original. Unfortunately, there is one big difference compared to the previous code: Before there was one call to boundary.IsConvex() to select the correct function to use, where now this method is called for every invocation of Contains! Although this is still faster than using the generic Contains method, most of the performance improvements are lost again (not to mention performance decreases for concave polygons).
A third possibility would be to have two public methods to check containment, where one of them assumes that the polygon is convex (without doing the check itself, of course, otherwise we're back to the previous overhead problem). This doesn't seem like a good idea, since calling it by accident with a concave polygon could give unexpected results, making for hard to find bugs.
So finally, my question is, is there any good way to deal with this situation? Where should we put the alternative Contains method, and how should we call it?
Edit
I like the idea of caching whether or not a polygon is convex. But I cannot change the interface nor the behavior of the class, which is problematic in a case such as this:
//relevant part of the polygon interface
public List<Point> Points { get; set; }
//client code
var poly = new Polygon();
var list = new List<Point>
{
new Point(0,0),
new Point(10,0),
new Point(0,10)
};
poly.Points = list;
list.Add(new Point(1, 1));
This last line of code is executed on a regular List<Point>, there is nothing I can do about that. However, there would now be 2 requirements:
The polygon must now contain the added point. This is to ensure existing code doesn't break. This means that we cannot copy the Points into our own, observable list.
We must get notified of this change to the list of points (because our polygon has turned from convex to concave). This means that we cannot wrap the list by our own, observable list, because only changes made through the wrapper would cause a notification.
One option is to create another concept in the geometry library, say FixedBoundary, which could encapsulate that logic. It would be immutable so that you could safely cache the convexity. An example:
public class FixedBoundary
{
private Polygon boundary;
private bool isConvex;
public FixedBoundary(Polygon boundary)
{
// deep clone so we don't have to worry about the boundary being modified later.
this.boundary = boundary.Clone();
this.isConvex = this.boundary.IsConvex();
}
public bool Contains(Polygon p)
{
if (isConvex)
{
// efficient convex logic here
}
else
{
return this.boundary.Contains(p);
}
}
}
This of course adds some conceptual weight to the geometry library. Another option would be to add an ImmutablePolygon (and by extension ImmutablePoint) which could do the same, however conversions may be cumbersome and affect performance as well.
You could replicate what you've done already with the Func<T, bool> delegate.. internal to the Polygon.. perhaps like this?
private Func<Polygon, bool> _containsFunc;
// ...
public bool Contains(Polygon other) {
if (_containsFunc == null) {
if (this.IsConvex())
_containsFunc = ConvexContains;
else
_containsFunc = GenericContains;
}
return _containsFunc(other);
}
Each call to Contains after the first will not call IsConvex. Unless I have misunderstood you.. that sounds like what you're after.
Okay...you guys really shot yourselves in the foot by using List in your public interface. Here is how you can try to solve it (there is a small non-zero chance that this will incorrectly cache, but its a 1 in (1 <<32 ) chance.
As you have noted, we could cache the polygon's Convexness...but the problem then becomes a case of Cache invalidation.
Without being able invalid cache on object change. You would have to check for cache coherence on each call. This is where hashing comes in.
By default the hash for list is quite useless, you want to use a this solution for getting a usable hash.
So what you want to do is to add a nullable<int> _cachedHashCode on your polygon. When you call Polygon.IsConvex, you hash your List<Point>, compare with your _cachedHashCode, and if they don't equal, recompute your IsConvex.

How to avoid casting from interface to class

In trying to design a collision detection component for a game, I came up with the following solution. I define an interface ICollideable that looks something like:
interface ICollideable
{
Sprite Sprite { get; }
int Damage { get; }
void HandleCollision(ICollideable collidedWith);
}
Basically, any game objects that want to participate in collision detection have to implement this interface, then register themselves with the detector, which maintains a list of ICollideables. When it detects a collision, it calls the HandleCollision method on the object and passes in a reference to the object it collided with.
I like this, because it lets me keep all my collision algorithms in one place, and lets the game objects themselves decide how to handle the collision. But because of the latter, I find I am having to check the underlying object type. For example, I don't want Players to collide with each other, so in the Player class there might be something like:
void HandleCollision(ICollideable collidedWith)
{
if (!(collidedWith is Player)) { // do stuff }
}
and so on, and I am wondering if this is telling me that I have a bad design and what the alternatives might be.
Second question, further along the lines of the first. For scoring purposes, if an Enemy is destroyed by a Projectile, someone needs to know the "Owning Player" member of the Projectile class. However, none of my other collideables have or need this property, so I find myself wanting to do (in the Enemy HandleCollision):
void HandleCollision(ICollideable collidedWith)
{
if (collidedWith is Projectile) {
Health -= collidedWith.Damage;
if (Health <= 0) {
Player whoDestroyedMe = (collidedWith as Projectile).FiredBy
// ...
}
}
}
I haven't a clue as to how to handle this with a better design. Any insights would be appreciated.
EDIT: I wanted to pull focus towards the second question, because my gut tells me a way of handling this will solve the first question. As for the first question, I thought of a way to abstract this behavior. I could define an enum:
enum Team
{
Player,
Enemy,
Neither
}
and have ICollideables implement this property. Then the collision detector simply doesn't register collisions between collideables on the same "Team". So, Player and Player Projectiles would be on one team, Enemy and Enemy Projectiles on the other, and the environment (which can damage both) can be on neither. It doesn't have to be an enum, could be an int or a string or anything, with the idea that objects with the same value for this property do not collide with each other.
I like this idea of modeling behavior with a simple attribute. For instance, if I want to turn "allow friendly fire" on, all I have to do is create Projectiles with a Team value other than the Player's Team value. However, I still may have cases where this is not enough. For example, a Player may have shields that are temporarily impervious to projectiles but will not protect against a direct collision with an enemy, and so on.
I think you're going the wrong way altogether in handling the collision inside of the class of one of the colliders. I would put this logic into a third object, outside of the entity objects. You could do all of the checking of the types in this third object, and even handle most of the logic there too. Why should a Ship or a Projectile have a monopoly over the logic that happens when one hits the other?
The following is how I might handle this, although it means using an object for each style of collision (Ship vs Ship, Ship vs Projectile, Ship vs Asteroid, etc.) You might be more comfortable putting all that logic into a single object, or even a single method on that object.
public interface ICollisionHandler
{
bool HandleCollision(Entity first, Entity second);
}
public class PlayerShipVsProjectile : ICollisionHandler
{
private GameOptions options;
public PlayersOwnShipHandler(GameOptions options)
{
this.options = options;
}
public bool HandleCollision(Entity first, Entity second)
{
// Exactly how you go about doing this line, whether using the object types
// or using a Type property, or some other method, is not really that important.
// You have so much more important things to worry about than these little
// code design details.
if ((!first is Ship) || (!second is Projectile)) return false;
Ship ship = (Ship)first;
Projectile projectile = (Projectile)second;
// Because we've decided to put this logic in it's own class, we can easily
// use a constructor parameter to get access to the game options. Here, we
// can have access to whether friendly fire is turned on or not.
if (ship.Owner.IsFriendlyWith(projectile.Shooter) &&
!this.options.FriendlyFire) {
return false;
}
if (!ship.InvulnerableTypes.Contains(InvulnerableTypes.PROJECTILE))
{
ship.DoDamage(projectile.Damage);
}
return true;
}
}
Like this, you can then do...
// Somewhere in the setup...
CollisionMapper mapper = new CollisionMapper();
mapper.AddHandler(new ShipVsProjectile(gameOptions));
mapper.AddHandler(new ShipVsShip(gameOptions));
// Somewhere in your collision handling...
mapper.Resolve(entityOne, entityTwo);
The implementation of CollisionMapper is left as an exercise for the reader. Remember that you might need to have Resolve call the ICollisionHandler's "Handle" method twice, with the second time reversing the entities (otherwise your collision handler objects will need to check for the reverse situation, which might be ok as well).
I feel this makes the code easier to read. A single object describes exactly what will happen when two entities collide, rather than trying to put all this info into one of the entity objects.
For the first case, I would add the following extra method to ICollidable:
bool CanCollideWith(ICollidable collidedWith)
As the name suggests, it would return true or false depending upon whether it can collide with the passed in object.
Your Player.HandleCollision method would just do its stuff because the calling method could do that test and not even call the method if it wasn't required.
How about something like this?
Collidable.cs
abstract class Collidable
{
public Sprite Sprite { get; protected set; }
public int Damage { get; protected set; }
protected delegate void CollisionAction(Collidable with);
protected Dictionary<Type, CollisionAction> collisionTypes = new Dictionary<Type, CollisionAction>();
public void HandleCollision(Collidable with)
{
Type collisionTargetType = with.GetType();
CollisionAction action;
bool keyFound = collisionTypes.TryGetValue(collisionTargetType, out action);
if (keyFound)
{
action(with);
}
}
}
Bullet.cs
class Bullet: Collidable
{
public Bullet()
{
collisionTypes.Add(typeof(Player), HandleBulletPlayerCollision);
collisionTypes.Add(typeof(Bullet), HandleBulletBulletCollision);
}
private void HandleBulletPlayerCollision(Collidable with)
{
Console.WriteLine("Bullet collided with {0}", with.ToString());
}
private void HandleBulletBulletCollision(Collidable with)
{
Console.WriteLine("Bullet collided with {0}.", with.ToString());
}
}
Player.cs
class Player : Collidable
{
public Player()
{
collisionTypes.Add(typeof(Bullet), HandlePlayerBulletCollision);
collisionTypes.Add(typeof(Player), HandlePlayerPlayerCollision);
}
private void HandlePlayerBulletCollision(Collidable with)
{
Console.WriteLine("Player collided with {0}.", with.ToString());
}
private void HandlePlayerPlayerCollision(Collidable with)
{
Console.WriteLine("Player collided with {0}.", with.ToString());
}
}
I think this is a good question #idlewire and I have to say that I don't think there is anything fundamentally wrong with your original solution. In asking whether object Foo should be allowed to cast the ICollideable to a Bar, the important question is only: is undesirable to have Foo knowing anything at all about Bar? If the answer is 'no' because Foo already knows about Bars (for behaviours other than collisions, perhaps) then I see no problem in the cast and, as you say, it allows you to better encapsulate the behaviour of both.
Where you need to be wary is only where this would introduces a dependency between two things you'd like kept apart - which would make re-use of either without the other (in a different game application for example) impossible. There you might want to either have more specific sub-interfaces from ICollideable (e.g. IElastic and IInelastic), or use properties on the interface as you have proposed with the Enum.
In short, I think your original posting shows good evidence of OO thinking, not bad.
Sometimes the simplest method is the best method. Unless you want to separate your collision interactions into numerous subtypes, you could instead place a bool IsPlayer property within the Interface.
The upside here is that you have a cheaper, and type safe method of determination over casting.
If (isplayer == true)
{
Handlethisway;
}
The downside is that you're still having to do some sort of state checking, but this is more efficient.
To avoid any state checks, you'd need to do the following: Make an ICollidablePlayer Interface which accepts generic Icollideable and handles them differently. Since the Icollideable is your injected dependency, the ICollideablePlayer dependencies are inherent. The objects of Icollideable would have no knowledge of this separate process, and interact with each other in the same manner.
ICollideablePlayer:ICollideable
{
//DependenciesHere
HandlePlayerCollision(ICollideable)
{
HandleDifferently
{
}
ICollideable
{
//DependenciesHere
HandleCollision(ICollideable)
}
}
}
In an interaction, the ICollideable will treat the player as any other ICollideable, but the ICollideablePlayer will reject the interaction when it does the check itself.
For things like shields and all that, You're talking about state changes which implies that those such things should be properties within either of those Interfaces such that something like bool ColliderOff to temporarily change the state.

Is it better to use out for multiple output values or return a combined value type?

For instance, along the lines of:
public bool Intersect (Ray ray, out float distance, out Vector3 normal)
{
}
vs
public IntersectResult Intersect (Ray ray)
{
}
public class IntersectResult
{
public bool Intersects {get;set;}
public float Distance {get;set;}
public Vector3 Normal {get;set;}
}
Which is better both for clarity, ease of use, and most importantly performance.
I would use a combined type and I'll tell you why: because computation of a value should return the value, not mutate a bunch of variables. Mutating a bunch of variables doesn't scale once you need more than one of them mutated. Suppose you want a thousand of these things:
IEnumerable<Ray> rays = GetAThousandRays();
var intersections = from ray in rays
where Intersect(ray, out distance, out normal)
orderby distance ...
Executing the query is now repeatedly mutating the same two variables. You're ordering based on a value that is being mutated. This is a mess. Don't make queries that mutate things; it is very confusing.
What you want is:
var intersections = from ray in rays
let intersection = Intersect(ray)
where intersection.Intersects
orderby intersection.Distance ...
No mutation; manipulate a sequence of values as values not as variables.
I also would be inclined to maybe get rid of that Boolean flag, and make the value an immutable struct:
// returns null if there is no intersection
Intersection? Intersect(Ray ray) { ... }
struct Intersection
{
public double Distance { get; private set; }
public Vector3 Normal { get; private set; }
public Intersection(double distance, Vector3 normal) : this()
{
this.Normal = normal;
this.Distance = distance;
}
}
I would use a combined type.
With an object you can attach behaviour, and return an arbitrarily complex object. You may wish to refactor your method in the future, and change the return values. By wrapping them in a return object and adding behaviour to that object, this refactoring can become largely transparent.
It's tempting to use tuples and the like. However the refactoring effort becomes a headache after a while (I'm speaking from experience here, having just made this mistake again)
It's best to return a combined type. At the very least your method signature is cleaner and there's less work for the programmer to do when calling it. EG: you don't have to declare and initialize variables, which clutters the calling code.
Some people say it's a matter of preference, but I think that returning a complex object is better not only for clarity, but for maintenance as well.
If you ever needed to add another bit of data as output, you would have to change the method signature in addition to adding the code for the extra response; not so with a complex output type. In addition, it's harder to mock (for unit testing) output parameters. It also seems to break the 'simple' philosophy - you're having to go through the trouble of getting the output parameters set up when you only need one piece of input. The strength of an OOP language is making types - go with that route in my opinion.
The performance difference between the two is negligible.
You could use a Tuple instead of creating the IntersectResult class as an alternative.
Reference:
http://msdn.microsoft.com/en-us/library/system.tuple.aspx
However, I would definitely lean toward returning a complex type over out parameters.
Just for the record:
It's hard to find a good example of the magic trio (clarity, ease of use, and performance).
Obviously the second example provides the first two, while the first one provides better performance. Whether this is negligible, I do not know. Maybe run a benchmark test and find out.
What I can tell you is that if you make your result type a small-sized struct, you can still save some performance points, since allocating on the heap is more expensive than on the stack. Again, copying the data from a value type can outweigh the heap-allocation penalty, but maybe not if you keep it small enough.
Furthermore, you probably want to make that type immutable.
Option 2 is probably the best solution if it best captures your domain. In which case your new type will get used in many other places as it represents a logical entity.
That depends entirely on how coherent the concept of an IntersectResult is.
Technically there is no reason to prefer one over the other.

Is this an abuse of the type system?

I'm working on a hobby project of the game Baroque Chess. For those that haven't played it, it has the same basic rules as chess, but the methods for movement and capturing are different.
Naturally I created standard classes for the game: GameState, Board, Square, and a class designated for each piece that inherit from a BasePiece.
Each piece has 2 main virtual methods, GetPossibleMoves(Board board) and GetCapturedSquares(Board board, Square toSquare).
Now, one of the pieces, the Imitator, captures pieces by "imitating" the piece that it captures. For example, a Long Leaper can capture pieces by jumping over them. This means that the Imitator can jump over enemy Long Leapers to capture them (but cannot jump anything else).
I completed the GetCapturedSquares() functionality for all the pieces except the Imitator (which is definitely the trickiest of the pieces).
My basic algorithm for the Imitator was:
find all the squares with enemy pieces on them
for each enemy piece...
create a simulated piece in the same location as the Imitator
find the valid captures if it were the simulated piece moving to a chosen square
verify the enemy square is in that list of captured squares
Since I had already written the code for the other pieces' movements, I figured I would just instantiate new pieces and use their GetCapturedSquares() methods depending on which type of piece the enemy was. To do this, I setup up a Dictionary as you can see here that maps a System.Type to an instantiated object of said type:
var typeToPiece = new Dictionary<Type, BasePiece>()
{
{typeof(Pincer), new Pincer() { Color = this.Color, CurrentSquare = this.CurrentSquare}},
{typeof(Withdrawer), new Withdrawer() { Color = this.Color, CurrentSquare = this.CurrentSquare }},
{typeof(Coordinator), new Coordinator() { Color = this.Color, CurrentSquare = this.CurrentSquare }},
{typeof(LongLeaper), new LongLeaper() { Color = this.Color, CurrentSquare = this.CurrentSquare }},
{typeof(King), new King() { Color = this.Color, CurrentSquare = this.CurrentSquare }},
};
//...
var possibleMoves = typeToPiece[enemySquare.Occupant.GetType()].GetPossibleMoves(board, toSquare);
Doing this makes me feel dirty inside. Is it more appropriate to create an enum or string that represents the piece type as the dictionary key, or does it really not matter? Is there a different way to handle this? I am of the opinion that it's fine just the way it is but I am interested in hearing your thoughts.
I think you should add an abstract method to BasePiece that "clones" the current piece and returns the simulated piece.
You'd override this method in every piece type. To share code between them, you can add a protected method to the base class that copies the shared properties to the instance passed to it:
abstract class BasePiece {
protected BasePiece(BasePiece pieceToClone) {
this.Color = pieceToClone.Color;
this.CurrentSquare = pieceToClone.CurrentSquare;
}
public abstract BasePiece GetSimulatedClone();
}
class King : BasePiece {
protected King(King pieceToClone) : base(pieceToClone) { }
public King() { }
public override BasePiece GetSimulatedClone() {
return new King(this);
}
}
In general, whenever you are switching based on the type of a variable, you should think twice and see if you can polymorphism instead.
This is a little more elegant to my mind:
private abstract class Piece {}
private class King : Piece { }
private class Imitator : Piece { }
private void main(object sender, EventArgs e) {
Piece x;
x = CreateNewPiece(new King());
x = CreateNewPiece(new Imitator());
}
private T CreateNewPiece<T>(T piece) where T : Piece, new() {
return new T();
}
It relies on the new() generic constraint to instantiate a type variable.
I personally agree that you're okay to do what you're doing since it's a small hobby project. If you really want to get around the problem you're describing, though, you could create a separate tier of Mover objects that handles the logic surrounding the actual movement of different pieces. Then, rather than asking a piece what moves it can do, you pass that piece's position information, along with the board state information, to the Mover, which tells you what moves that piece could make. The Mover associated with an Imitator could then be a combination of all the other movers in the way you describe, but without the need to create fake "pieces" on the fly.
Another suggestion I'd make, which is more related to logic than to your model, is to change your logic like so:
for each piece type (or mover type)
create a simulated piece in the same location as the Imitator
find the valid captures if it were the simulated piece moving to a chosen square
only keep the captures where the occupant of the enemy square is of the piece type you're checking
This is a subtle difference, but will significantly reduce the amount of calculation required.
Update
Recursive's comment made me realize I may not have been clear enough about how the Mover tier would work. The idea is to have a KingMover, PincerMover, and so forth, which know about the moves for a specific piece type. Since they're tied to a piece's type rather than the piece itself, they could even be singletons. Each piece type could have a Mover field that points to its mover, and then either your business logic could call that Mover's GetPossibleMoves method directly, or your piece's GetPossibleMoves method could simply call the Mover's method, passing itself in as an argument. The ImitatorMover would know to ask each other type of mover for its possible moves, and then filter those moves based on whether they would be attacking a piece of the type associated with that mover.
You'd have almost the same code as in the current system, but the code for each Piece could really just focus on representing that Piece's information (position, color, etc.), whereas the code for actually determining how a piece moves would be moved into a separate tier of classes. Each class would have a single purpose.
Without touching this specific problem, there's nothing inherently wrong with the idea of a dictionary that lets you look up objects by their type. In fact, .NET FCL provides such a type already - it's called KeyedByTypeCollection<T>. It's probably better for such things, because it ensures that key of an object is its type as returned by GetType() (and not some other random type), and won't let you add two objects of the same type.

Help on implementing how creatures and items interact in a computer role playing game

I am programming a simple role playing game (to learn and for fun) and I'm at the point where I'm trying to come up with a way for game objects to interact with each other. There are two things I am trying to avoid.
Creating a gigantic game object that can be anything and do everything
Complexity - so I am staying away from a component based design like you see here
So with those parameters in mind I need advice on a good way for game objects to perform actions on each other.
For example
Creatures (Characters, Monsters, NPCs) can perform actions on Creatures or Items (weapons, potions, traps, doors)
Items can perform actions on Creatures or Items as well. An example would be a trap going off when a character tries to open a chest
What I've come up with is a PerformAction method that can take Creatures or Items as parameters. Like this
PerformAction(Creature sourceC, Item sourceI, Creature targetC, Item targetI)
// this will usually end up with 2 null params since
// only 1 source and 1 target will be valid
Or should I do this instead?
PerformAction(Object source, Object target)
// cast to correct types and continue
Or is there a completely different way I should be thinking about this?
This is a "double dispatch" problem. In regular OO programming, you "dispatch" the operation of a virtual method call to the concrete type of the class implementing the object instance you call against. A client doesn't need to know the actual implementation type, it is simply making a method call against an abstract type description. That's "single dispatch".
Most OO languages don't implement anything but single-dispatch. Double-dispatch is when the operation that needs to be called depends on two different objects. The standard mechanism for implementing double dispatch in OO languages without direct double-dispatch support is the "Visitor" design pattern. See the link for how to use this pattern.
This sounds like a case for polymorphism. Instead of taking Item or Creature as an argument, make both of them derive (or implement) from ActionTarget or ActionSource. Let the implementation of Creature or Item determine which way to go from there.
You very rarely want to leave it so open by just taking Object. Even a little information is better than none.
You can try mixing the Command pattern with some clever use of interfaces to solve this:
// everything in the game (creature, item, hero, etc.) derives from this
public class Entity {}
// every action that can be performed derives from this
public abstract class Command
{
public abstract void Perform(Entity source, Entity target);
}
// these are the capabilities an entity may have. these are how the Commands
// interact with entities:
public interface IDamageable
{
void TakeDamage(int amount);
}
public interface IOpenable
{
void Open();
}
public interface IMoveable
{
void Move(int x, int y);
}
Then a derived Command downcasts to see if it can do what it needs to the target:
public class FireBallCommand : Command
{
public override void Perform(Entity source, Entity target)
{
// a fireball hurts the target and blows it back
var damageTarget = target as IDamageable;
if (damageTarget != null)
{
damageTarget.TakeDamage(234);
}
var moveTarget = target as IMoveable;
if (moveTarget != null)
{
moveTarget.Move(1, 1);
}
}
}
Note that:
A derived Entity only has to implement the capabilities that are appropriate for it.
The base Entity class doesn't have code for any capability. It's nice and simple.
Commands can gracefully do nothing if an entity is unaffected by it.
I think you're examining too small a part of the problem; how do you even determine the arguments to the PerformAction function in the first place? Something outside of the PerformAction function already knows (or somehow must find out) whether the action it wants to invoke requires a target or not, and how many targets, and which item or character it's operating upon. Crucially, some part of the code must decide what operation is taking place. You've omitted that from the post but I think that is the absolute most important aspect, because it's the action that determines the required arguments. And once you know those arguments, you know the form of the function or method to invoke.
Say a character has opened a chest, and a trap goes off. You presumably already have code which is an event handler for the chest being opened, and you can easily pass in the character that did it. You also presumably already ascertained that the object was a trapped chest. So you have the information you need already:
// pseudocode
function on_opened(Character opener)
{
this.triggerTrap(opener)
}
If you have a single Item class, the base implementation of triggerTrap will be empty, and you'll need to insert some sort of checks, eg. is_chest and is_trapped. If you have a derived Chest class, you'll probably just need is_trapped. But really, it's only as difficult as you make it.
Same goes for opening the chest in the first place: your input code will know who is acting (eg. the current player, or the current AI character), can determine what the target is (by finding an item under the mouse, or on the command line), and can determine the required action based on the input. It then simply becomes a case of looking up the right objects and calling the right method with those arguments.
item = get_object_under_cursor()
if item is not None:
if currently_held_item is not None:
player_use_item_on_other_item(currently_held_item, item)
else
player.use_item(item)
return
character = get_character_under_cursor()
if character is not None:
if character.is_friendly_to(player):
player.talk_to(character)
else
player.attack(character)
return
Keep it simple. :)
in the Zork model, each action one can do to an object is expressed as a method of that object, e.g.
door.Open()
monster.Attack()
something generic like PerformAction will end up being a big ball of mud...
What about having a method on your Actors (creatures, items) that Perform the action on a target(s). That way each item can act differently and you won't have one big massive method to deal with all the individual items/creatures.
example:
public abstract bool PerformAction(Object target); //returns if object is a valid target and action was performed
I've had a similar situation to this, although mine wasn't Role playing, but devices that sometimes had similar characteristics to other devices, but also some characteristics that are unique. The key is to use Interfaces to define a class of actions, such as ICanAttack and then implement the particular method on the objects. If you need common code to handle this across multiple objects and there's no clear way to derive one from the other then you simply use a utility class with a static method to do the implementation:
public interface ICanAttack { void Attack(Character attackee); }
public class Character { ... }
public class Warrior : Character, ICanAttack
{
public void Attack(Character attackee) { CharacterUtils.Attack(this, attackee); }
}
public static class CharacterUtils
{
public static void Attack(Character attacker, Character attackee) { ... }
}
Then if you have code that needs to determine whether a character can or can't do something:
public void Process(Character myCharacter)
{
...
ICanAttack attacker = null;
if ((attacker = (myCharacter as ICanAttack)) != null) attacker.Attack(anotherCharacter);
}
This way, you explicitly know what capabilities any particular type of character has, you get good code reuse, and the code is relatively self-documenting. The main drawback to this is that it is easy to end up with objects that implement a LOT of interfaces, depending on how complex your game is.
This might not be something that many would agree upon, but I'm not a team and it works for me (in most cases).
Instead of thinking of every Object as a collection of stuff, think of it as a collection of references to stuff. Basically, instead of one huge list of many
Object
- Position
- Legs
- [..n]
You would have something like this (with values stripped, leaving only relationships):
Whenever your player (or creature, or [..n]) wants to open a box, simply call
Player.Open(Something Target); //or
Creature.Open(Something Target); //or
[..n].Open(Something Target);
Where "Something" can be a set of rules, or just an integer which identifies the target (or even better, the target itself), if the target exists and indeed can be opened, open it.
All this can (quite) easily be implemented through a series of, say interfaces, like this:
interface IDraggable
{
void DragTo(
int X,
int Y
);
}
interface IDamageable
{
void Damage(
int A
);
}
With clever usage of these interfaces you might even ending up using stuff like delegates to make an abstraction between top-level
IDamageable
and the sub-level
IBurnable
Hope it helped :)
EDIT: This was embarassing, but it seems I hijacked #munificent's answer! I'm sorry #munificent! Anyway, look at his example if you want an actual example instead of an explanation of how the concept works.
EDIT 2: Oh crap. I just saw that you clearly stated you didn't want any of the stuff that was contained in the article you linked, which clearly is exactly the same as I have written about here! Disregard this answer if you like and sorry for it!

Categories

Resources