/**
   * Implements Speed special movement/attack model.
   *
   * @param board
   * @param mtkn
   * @return
   */
  public List<Vector2D> powerMovementSystemSpeed(Board board, MovablePlayerToken mtkn) {
    List<Vector2D> movements = new ArrayList<Vector2D>();
    List<Vector2D> extraMovements = new ArrayList<Vector2D>();
    // Make consecutive movements:
    int x = mtkn.getCol();
    int y = mtkn.getRow();

    movements.add(new Vector2D(y - 1, x));
    movements.add(new Vector2D(y + 1, x));
    movements.add(new Vector2D(y, x - 1));
    movements.add(new Vector2D(y, x + 1));

    movements = validInBoard(movements);
    movements = validInPlayer(board, movements);

    for (int k = 0; k < movements.size(); k++) {
      if (board.getToken(movements.get(k).y, movements.get(k).x).getOwn()
          != this.getTurn().otherSide()) {
        extraMovements.add(new Vector2D(movements.get(k).y - 1, movements.get(k).x));
        extraMovements.add(new Vector2D(movements.get(k).y + 1, movements.get(k).x));
        extraMovements.add(new Vector2D(movements.get(k).y, movements.get(k).x - 1));
        extraMovements.add(new Vector2D(movements.get(k).y, movements.get(k).x + 1));
      }
    }

    extraMovements = validInBoard(extraMovements);
    extraMovements = validInPlayer(board, extraMovements);

    movements.addAll(extraMovements);

    return movements;
  }
 /**
  * Valid classic (cross-like) attack positions for each position in input list, that enemy Token
  * exists.
  *
  * @param board
  * @param loc
  * @return
  */
 public List<Vector2D> validForAttack(Board board, List<Vector2D> loc) {
   for (int i = loc.size() - 1; i >= 0; i--) {
     if (!(board.getToken(loc.get(i).y, loc.get(i).x).getOwn() == this.getTurn().otherSide())) {
       loc.remove(i);
     }
   }
   return loc;
 }
 /**
  * Converts the input PlayerToken to the other side. The particular token can not be converted
  * back, till the end of the game.
  *
  * @param board
  * @param tkn PlayerToken to be converted.
  */
 public void convertToken(Board board, PlayerToken tkn) {
   // Check if PlayerToken is converted previously:
   boolean isconverted = board.isConverted(tkn);
   if (!isconverted) {
     // Come to the dark side, we have cookies..
     tkn.setOwn(this.getTurn().side());
     this.getTurn().side().tokens.add(tkn);
     board.convertedTokens.add(tkn);
   }
 }
 /**
  * Filter valid movements in order to not conflict with same player Tokens.
  *
  * @param board
  * @param loc
  * @return
  */
 public List<Vector2D> validInPlayer(Board board, List<Vector2D> loc) {
   // remove locations if they fall on same player tokens:
   for (int i = loc.size() - 1; i >= 0; i--) {
     // Smarter way to check:
     // Not valid location if same player token overlap.
     if (board.getToken(loc.get(i).y, loc.get(i).x).getOwn() == this.getTurn().side()) {
       loc.remove(i);
     }
   }
   return loc;
 }
 /**
  * Saves the lost (input) Token and places it back to the board in the first empty position. If no
  * empty position Token is not saved.
  *
  * @param board
  * @param tkn
  * @return
  */
 public boolean saveToken(Board board, MovablePlayerToken tkn) {
   // Check if input Token is indeed killed;
   if (tkn.getCol() >= 0) {
     return false;
   }
   // Move the selected Token into the board (if possible!):
   if (getTurn().side().pname.equals("Fire")) {
     // find the first empty spot:
     for (int k = 0; k < 30; k++) {
       int r = k / 10 + 5;
       int c = k % 10;
       if (board.getToken(r, c) instanceof Grass) {
         this.insertToken2Board(board, tkn, r, c);
         return true;
       }
     }
   }
   return false;
 }
  /**
   * Checks if input position has valid attack options:
   *
   * @param loc query position.
   * @return List with possible attack options.
   */
  public List<Vector2D> positionsAttackOptions(Board board, Vector2D pos) {
    List<Vector2D> attackPositions = new ArrayList<Vector2D>();

    int y = pos.y;
    int x = pos.x;

    // Add the clasic attack positions:
    attackPositions.add(new Vector2D(y - 1, x));
    attackPositions.add(new Vector2D(y + 1, x));
    attackPositions.add(new Vector2D(y, x - 1));
    attackPositions.add(new Vector2D(y, x + 1));

    attackPositions = validInBoard(attackPositions);

    for (int k = 0; k < attackPositions.size(); k++) {
      if (!(board.getToken(attackPositions.get(k).y, attackPositions.get(k).x).getOwn()
          == this.getTurn().otherSide())) {
        attackPositions.remove(k);
      }
    }

    return attackPositions;
  }
  /**
   * Implements Dragon moving/attack model.
   *
   * @param board
   * @param drg
   * @return
   */
  public List<Vector2D> powerMovementSystemFlight(Board board, Dragon drg) {
    List<Vector2D> drgMovements = new ArrayList<Vector2D>();
    // move in each direction skipping first obstacle:
    int x = drg.getCol();
    int y = drg.getRow();

    boolean mustLand = false;
    boolean obstacle = false;
    List<Vector2D> safeLanding = new ArrayList<Vector2D>();
    List<Vector2D> riskyLanding = new ArrayList<Vector2D>();
    List<Vector2D> attackAfterLanding = new ArrayList<Vector2D>();
    // Negative Y:
    int ny = y;
    while (!mustLand) {
      ny--;
      if (isInsideBoard(new Vector2D(ny, x))) {
        Token bt = board.getToken(ny, x);
        /*if(!isInsideBoard(new Vector2D(ny,x))){
        	mustLand = true;
        }else */
        if (hitsRock(new Vector2D(ny, x))) {
          riskyLanding.add(new Vector2D(ny, x));
          obstacle = true;
        } else if (bt instanceof PlayerToken) {
          riskyLanding.add(new Vector2D(ny, x));
          obstacle = true;
        } else if (obstacle) {
          riskyLanding.add(new Vector2D(ny, x));
          safeLanding.addAll(riskyLanding);
          mustLand = true;
        } else {
          // If no better position is found, glide down with pride (like a true dragon):
          safeLanding.add(new Vector2D(ny, x));
        }
      } else {
        // Hit the end of the board:
        mustLand = true;
      }
    }

    mustLand = false;
    obstacle = false;
    riskyLanding = new ArrayList<Vector2D>();
    // Positive Y:
    ny = y;
    while (!mustLand) {
      ny++;
      if (isInsideBoard(new Vector2D(ny, x))) {
        Token bt = board.getToken(ny, x);
        if (hitsRock(new Vector2D(ny, x))) {
          riskyLanding.add(new Vector2D(ny, x));
          obstacle = true;
        } else if (bt instanceof PlayerToken) {
          riskyLanding.add(new Vector2D(ny, x));
          obstacle = true;
        } else if (obstacle) {
          riskyLanding.add(new Vector2D(ny, x));
          safeLanding.addAll(riskyLanding);
          mustLand = true;
        } else {
          safeLanding.add(new Vector2D(ny, x));
        }
      } else {
        // Hit the end of the board:
        mustLand = true;
      }
    }

    mustLand = false;
    obstacle = false;
    riskyLanding = new ArrayList<Vector2D>();
    // Negative X:
    int nx = x;
    while (!mustLand) {
      nx--;
      if (isInsideBoard(new Vector2D(y, nx))) {
        Token bt = board.getToken(y, nx);
        if (hitsRock(new Vector2D(y, nx))) {
          riskyLanding.add(new Vector2D(y, nx));
          obstacle = true;
        } else if (bt instanceof PlayerToken) {
          riskyLanding.add(new Vector2D(y, nx));
          obstacle = true;
        } else if (obstacle) {
          riskyLanding.add(new Vector2D(y, nx));
          safeLanding.addAll(riskyLanding);
          mustLand = true;
        } else {
          safeLanding.add(new Vector2D(y, nx));
        }
      } else {
        // Hit the end of the board:
        mustLand = true;
      }
    }

    mustLand = false;
    obstacle = false;
    riskyLanding = new ArrayList<Vector2D>();
    // Positive X:
    nx = x;
    while (!mustLand) {
      nx++;
      if (isInsideBoard(new Vector2D(y, nx))) {
        Token bt = board.getToken(y, nx);
        if (hitsRock(new Vector2D(y, nx))) {
          riskyLanding.add(new Vector2D(y, nx));
          obstacle = true;
        } else if (bt instanceof PlayerToken) {
          riskyLanding.add(new Vector2D(y, nx));
          obstacle = true;
        } else if (obstacle) {
          riskyLanding.add(new Vector2D(y, nx));
          safeLanding.addAll(riskyLanding);
          mustLand = true;
        } else {
          safeLanding.add(new Vector2D(y, nx));
        }
      } else {
        // Hit the end of the board:
        mustLand = true;
      }
    }

    // Define additional attack options for each landing position:
    for (int k = 0; k < safeLanding.size(); k++) {
      attackAfterLanding.addAll(
          positionsAttackOptions(board, new Vector2D(safeLanding.get(k).y, safeLanding.get(k).x)));
    }

    drgMovements.addAll(safeLanding);
    drgMovements.addAll(attackAfterLanding);

    return drgMovements;
  }
  /**
   * Implements Scout moving model.
   *
   * @param board
   * @param sct
   * @return
   */
  public List<Vector2D> movementSystemScout(Board board, Scout sct) {
    List<Vector2D> sctMovements = new ArrayList<Vector2D>();
    // move in each direction until hitting something:
    int x = sct.getCol();
    int y = sct.getRow();
    // Blocked by:
    // 1.rock (non-inclusive)
    // 2.same player token (non-inclusive)
    // 3.other player token (inclusive)
    // 4.Board boundaries (non-inclusive)
    boolean blocked = false;
    // Negative Y:
    int ny = y;
    while (!blocked) {
      ny--;
      if (isInsideBoard(new Vector2D(ny, x))) {
        Token bt = board.getToken(ny, x);
        if (hitsRock(new Vector2D(ny, x))) {
          blocked = true;
        } else if (bt.getOwn() == this.getTurn().side()) {
          blocked = true;
        } else if (bt.getOwn() == this.getTurn().otherSide()) {
          sctMovements.add(new Vector2D(ny, x));
          blocked = true;
        } else {
          sctMovements.add(new Vector2D(ny, x));
        }
      } else {
        blocked = true;
      }
    }
    blocked = false;
    // Positive Y:
    ny = y;
    while (!blocked) {
      ny++;
      if (isInsideBoard(new Vector2D(ny, x))) {
        Token bt = board.getToken(ny, x);
        if (hitsRock(new Vector2D(ny, x))) {
          blocked = true;
        } else if (bt.getOwn() == this.getTurn().side()) {
          blocked = true;
        } else if (bt.getOwn() == this.getTurn().otherSide()) {
          sctMovements.add(new Vector2D(ny, x));
          blocked = true;
        } else {
          sctMovements.add(new Vector2D(ny, x));
        }
      } else {
        blocked = true;
      }
    }
    blocked = false;
    // Negative X:
    int nx = x;
    while (!blocked) {
      nx--;
      if (isInsideBoard(new Vector2D(y, nx))) {
        Token bt = board.getToken(y, nx);
        if (hitsRock(new Vector2D(y, nx))) {
          blocked = true;
        } else if (bt.getOwn() == this.getTurn().side()) {
          blocked = true;
        } else if (bt.getOwn() == this.getTurn().otherSide()) {
          sctMovements.add(new Vector2D(y, nx));
          blocked = true;
        } else {
          sctMovements.add(new Vector2D(y, nx));
        }
      } else {
        blocked = true;
      }
    }
    blocked = false;
    // Positive X:
    nx = x;
    while (!blocked) {
      nx++;
      if (isInsideBoard(new Vector2D(y, nx))) {
        Token bt = board.getToken(y, nx);
        if (hitsRock(new Vector2D(y, nx))) {
          blocked = true;
        } else if (bt.getOwn() == this.getTurn().side()) {
          blocked = true;
        } else if (bt.getOwn() == this.getTurn().otherSide()) {
          sctMovements.add(new Vector2D(y, nx));
          blocked = true;
        } else {
          sctMovements.add(new Vector2D(y, nx));
        }
      } else {
        blocked = true;
      }
    }

    return sctMovements;
  }