package hu.kazocsaba.gamecracker.game;

/**
 * Represents a move of a game. From the perspective of the API, a move is only used in relation to a position, so it
 * does not need to contain any information beyond what is required to interpret it in the context of a position.
 * <p>
 * Implementations of this interface should be immutable.
 * 
 * @param <M> the concrete Move type
 * @param <T> the concrete Transformation type
 * @author Kazó Csaba
 */
public interface Move<M extends Move<M, T>, T extends Transformation<T>> {
	/**
	 * Transforms this move with the specified transformation and returns the result.
	 * 
	 * @param t the transformation to apply
	 * @return the result of the transformation
	 * @throws IllegalArgumentException if the argument is not a valid transformation for this game
	 */
	public M transform(T t);
}

@@ -455,25 +455,30 @@
 %0Apublic 
-interface
+abstract class
  Move%3CM 
@@ -817,16 +817,25 @@
 %09public 
+abstract 
 M transf
@@ -844,10 +844,744 @@
 m(T t);%0A
+%09%0A%09/**%0A%09 * Returns whether the specified object is %22equal to%22 this one. Beside the general contract of the equals method,%0A%09 * it is required that if two moves %7B@code m1%7D and %7B@code m2%7D are equal, then for any position %7B@code pos%7D:%0A%09 * %3Col%3E%0A%09 * %3Cli%3Eif %7B@code m1%7D is valid in %7B@code pos%7D, then %7B@code m2%7D must also be valid, and they must lead to equal%0A%09 * positions: %7B@code pos.move(m1).equals(pos.move(m2))%7D;%3C/li%3E%0A%09 * %3Cli%3Eif %7B@code m1%7D is not valid in %7B@code pos%7D, then %7B@code m2%7D must also be invalid.%3C/li%3E%0A%09 * %3C/ol%3E%0A%09 * %0A%09 * @param obj the object with which to compare%0A%09 * @return true if this object is equal to the argument%0A%09 */%0A%09@Override%0A%09public abstract boolean equals(Object obj);%0A%0A%09@Override%0A%09public abstract int hashCode();%0A
 %7D%0A

Make Move an abstract class and define equals and hashCode, otherwise I forget them in implementations.