private Link GetStraitJumpLink(Square square, Link link) { Square target = link.LinkedSquare(square); // Check strait jump first int jumpX = target.X + (target.X - square.X); int jumpY = target.Y + (target.Y - square.Y); Square straitJump = target.Neighbours.FirstOrDefault(s => s.X == jumpX && s.Y == jumpY); if (straitJump == null) { return null; } MoveResult fromTarget = GetMoveResult(target, straitJump); switch (fromTarget) { case MoveResult.Succesfull: return new JumpLink(square, target, straitJump); case MoveResult.BlockedByFence: case MoveResult.BlockedByPlayer: return null; default: throw new InvalidOperationException("Unexpected move result."); } }
// Assumes the linked square is ocupied by player private IEnumerable<Link> GetJumpLinks(Square square, Link link) { // Jump links are used in the case one player stands in front of the other. // Jump links aren't presisted as they become stale quickly // Jumps can be made over a single player. // In case strait jump not possible because of the fences diagonal jumps can be made if aren't blocked by fences. Square target = link.LinkedSquare(square); Link straitJump = GetStraitJumpLink(square, link); if (straitJump != null) { yield return straitJump; yield break; } // handle diagonal jumps foreach (var l in GetDiagonalJumpLinks(square, link)) { yield return l; } }
private IEnumerable<Link> GetDiagonalJumpLinks(Square square, Link link) { Square target = link.LinkedSquare(square); int deltaX = target.X - square.X; int deltaY = target.Y - square.Y; int[] jumpDirection = { -1, 1 }; foreach (int direction in jumpDirection) { int jumpX = deltaX == 0 ? target.X + direction : target.X; int jumpY = deltaY == 0 ? target.Y + direction : target.Y; Square diagonalJump = target.Neighbours.FirstOrDefault(s => s.X == jumpX && s.Y == jumpY); if (diagonalJump == null) { continue; } MoveResult fromTarget = GetMoveResult(target, diagonalJump); switch (fromTarget) { case MoveResult.Succesfull: yield return new JumpLink(square, target, diagonalJump); break; case MoveResult.BlockedByFence: case MoveResult.BlockedByPlayer: break; default: throw new InvalidOperationException("Unexpected move result."); } } }
/// <summary> /// Moves player in by the link. /// </summary> /// <param name="player"></param> /// <param name="link"></param> protected void MovePlayer(Player player, Link link) { Square currentPosition = player.Position; // Validate current -> desired is not bloced by fence and isn't occupied if (GetMoveResult(currentPosition, link) != MoveResult.Succesfull) { throw new InvalidOperationException("Can not jump over the fence or step on the other player."); } Square newPosition = link.LinkedSquare(currentPosition); ((MovablePlayer)player).MoveTo(newPosition); }
/// <summary> /// /// </summary> /// <param name="from"></param> /// <param name="link"></param> /// <returns></returns> public MoveResult GetMoveResult(Square from, Link link) { JumpLink jumpLink = link as JumpLink; if (jumpLink != null) { if (GetMoveResult(from, jumpLink.Via) != MoveResult.BlockedByPlayer) { return MoveResult.Invalid; } return GetMoveResult(jumpLink.Via, jumpLink.LinkedSquare(from)); } // Blocked by fence has higher priority than blocked by player so it goes first. if (Fences.Any(f => f.SplittedLinks.Contains(link))) { return MoveResult.BlockedByFence; } if (IsSquareOccupied(link.LinkedSquare(from))) { return MoveResult.BlockedByPlayer; } return MoveResult.Succesfull; }
/// <summary> /// /// </summary> /// <param name="link"></param> public void MoveCurrentPlayer(Link link) { // check link is not null if (!GameFinished) { if (!link.Squares.Contains(CurrentPlayer.Position)) { throw new InvalidOperationException("Invalid link provided."); } Square target = link.LinkedSquare(CurrentPlayer.Position); _board.MovePlayer(CurrentPlayer, link); GameFinished = CheckWinningConditions(); if (!GameFinished) { _currentPlayer = NextPlayer(); } } }