// Path: puzlib/src/main/java/com/totsp/crossword/puz/Playboard.java
// public static class Position implements Serializable {
//     public int across;
//     public int down;
// 
//     protected Position(){
// 
//     }
// 
//     public Position(int across, int down) {
//         this.down = down;
//         this.across = across;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if ((o == null) || (o.getClass() != this.getClass())) {
//             return false;
//         }
// 
//         Position p = (Position) o;
// 
//         return ((p.down == this.down) && (p.across == this.across));
//     }
// 
//     @Override
//     public int hashCode() {
//         return Arrays.hashCode(new int[] {across, down});
//     }
// 
//     @Override
//     public String toString() {
//         return "[" + this.across + " x " + this.down + "]";
//     }
// }
// 
// Path: puzlib/src/main/java/com/totsp/crossword/puz/Playboard.java
// public static class Word implements Serializable {
//     public Position start;
//     public boolean across;
//     public int length;
// 
//     public boolean checkInWord(int across, int down) {
//         int ranging = this.across ? across : down;
//         boolean offRanging = this.across ? (down == start.down) : (across == start.across);
// 
//         int startPos = this.across ? start.across : start.down;
// 
//         return (offRanging && (startPos <= ranging) && ((startPos + length) > ranging));
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (o.getClass() != Word.class) {
//             return false;
//         }
// 
//         Word check = (Word) o;
// 
//         return check.start.equals(this.start) && (check.across == this.across) && (check.length == this.length);
//     }
// 
//     @Override
//     public int hashCode() {
//         int hash = 5;
//         hash = (29 * hash) + ((this.start != null) ? this.start.hashCode() : 0);
//         hash = (29 * hash) + (this.across ? 1 : 0);
//         hash = (29 * hash) + this.length;
// 
//         return hash;
//     }
// }


import com.totsp.crossword.puz.Playboard.Position;
import com.totsp.crossword.puz.Playboard.Word;
import java.io.Serializable;
import java.util.Arrays;
package com.totsp.crossword.puz;



public interface MovementStrategy extends Serializable {

    class Common {

		/**
		 * @return if @param Word (w) is the last word in its direction in the @param board
		 */
		static boolean isLastWordInDirection(Playboard board, Word w) {
			return isLastWordInDirection(board.getBoxes(), w);
		}

		/**
		 * @return if @param Word (w) is the last word in its direction in @param boxes
		 */
		static boolean isLastWordInDirection(Box[][] boxes, Word w) {
			if (w.across) {
				return (w.start.across + w.length >= boxes.length);
			}
			return (w.start.down + w.length >= boxes[w.start.across].length);
		}

		/**
		 * @return if @param Position (p) is the last position in @param Word (w)
		 */
// Path: puzlib/src/main/java/com/totsp/crossword/puz/Playboard.java
// public static class Position implements Serializable {
//     public int across;
//     public int down;
// 
//     protected Position(){
// 
//     }
// 
//     public Position(int across, int down) {
//         this.down = down;
//         this.across = across;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if ((o == null) || (o.getClass() != this.getClass())) {
//             return false;
//         }
// 
//         Position p = (Position) o;
// 
//         return ((p.down == this.down) && (p.across == this.across));
//     }
// 
//     @Override
//     public int hashCode() {
//         return Arrays.hashCode(new int[] {across, down});
//     }
// 
//     @Override
//     public String toString() {
//         return "[" + this.across + " x " + this.down + "]";
//     }
// }
// 
// Path: puzlib/src/main/java/com/totsp/crossword/puz/Playboard.java
// public static class Word implements Serializable {
//     public Position start;
//     public boolean across;
//     public int length;
// 
//     public boolean checkInWord(int across, int down) {
//         int ranging = this.across ? across : down;
//         boolean offRanging = this.across ? (down == start.down) : (across == start.across);
// 
//         int startPos = this.across ? start.across : start.down;
// 
//         return (offRanging && (startPos <= ranging) && ((startPos + length) > ranging));
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (o.getClass() != Word.class) {
//             return false;
//         }
// 
//         Word check = (Word) o;
// 
//         return check.start.equals(this.start) && (check.across == this.across) && (check.length == this.length);
//     }
// 
//     @Override
//     public int hashCode() {
//         int hash = 5;
//         hash = (29 * hash) + ((this.start != null) ? this.start.hashCode() : 0);
//         hash = (29 * hash) + (this.across ? 1 : 0);
//         hash = (29 * hash) + this.length;
// 
//         return hash;
//     }
// }


// Path: puzlib/src/main/java/com/totsp/crossword/puz/MovementStrategy.java
import com.totsp.crossword.puz.Playboard.Position;
import com.totsp.crossword.puz.Playboard.Word;
import java.io.Serializable;
import java.util.Arrays;

package com.totsp.crossword.puz;



public interface MovementStrategy extends Serializable {

    class Common {

		/**
		 * @return if @param Word (w) is the last word in its direction in the @param board
		 */
		static boolean isLastWordInDirection(Playboard board, Word w) {
			return isLastWordInDirection(board.getBoxes(), w);
		}

		/**
		 * @return if @param Word (w) is the last word in its direction in @param boxes
		 */
		static boolean isLastWordInDirection(Box[][] boxes, Word w) {
			if (w.across) {
				return (w.start.across + w.length >= boxes.length);
			}
			return (w.start.down + w.length >= boxes[w.start.across].length);
		}

		/**
		 * @return if @param Position (p) is the last position in @param Word (w)
		 */
		static boolean isWordEnd(Position p, Word w) {