static FastIndex() { var directions = EnumArray <HexNeighborDirection> .Values; NeighborMap = new FastIndex[85 * directions.Length]; MirrorMap = new FastIndex[85]; for (byte i = 0; i < 85; i++) { var slowIndex = Index.CalculateFromByte(i); int offsetStart = i * directions.Length; for (int j = 0; j < directions.Length; j++) { HexNeighborDirection direction = directions[j]; FastIndex neighbor = FastIndex.Invalid; if (slowIndex.TryGetNeighbor(direction, out Index slowNeighbor)) { neighbor = new FastIndex(slowNeighbor); } NeighborMap[offsetStart + j] = neighbor; } MirrorMap[i] = CalculateMirror(FromByte(i)); } }
public FastIndex?GetNeighborAt(HexNeighborDirection direction) { if (TryGetNeighbor(direction, out FastIndex index)) { return(index); } return(null); }
public Index this[HexNeighborDirection dir] { get { if (TryGetNeighbor(dir, out Index neighbor)) { return(neighbor); } return(Index.invalid); } }
public bool TryGetNeighbor(HexNeighborDirection direction, out FastIndex index) { if (IsInBounds) { index = NeighborMap[HexId * 6 + (int)direction]; return(index.IsInBounds); } else { index = Invalid; return(false); } }
static IEnumerable <FastIndex> GenerateRay(FastIndex start, HexNeighborDirection direction) { FastIndex target = start; for (int j = 0; j < 20; j++) { target = target[direction]; if (!target.IsInBounds) { break; } yield return(target); } }
public void UpdateEdge(HexNeighborDirection toUpdate) { #if UNITY_EDITOR Material mat = new Material(meshRenderer.sharedMaterial); mat.SetFloat( name: $"_Edge{(int)toUpdate}", value: Mathf.Abs(meshRenderer.sharedMaterial.GetFloat($"_Edge{(int)toUpdate}") - 1).Floor() ); meshRenderer.material = mat; #elif !UNITY_EDITOR meshRenderer.material.SetFloat( name: $"_Edge{(int)toUpdate}", value: Mathf.Abs(meshRenderer.material.GetFloat($"_Edge{(int)toUpdate}") - 1).Floor() ); #endif }
public void ShiftComprehensivetest([ValueSource(typeof(PrecomputedMoveData), nameof(PrecomputedMoveData.AllDirections))] HexNeighborDirection direction) { for (byte b = 0; b < 85; b++) { FastIndex index = FastIndex.FromByte(b); var original = new BitsBoard(); original[index] = true; var expected = index[direction]; var shifted = original.Shift(direction); if (expected.IsInBounds) { AssertOnlyIndexSet(shifted, expected); } else { AssertNoIndicesSet(shifted); } } }
private (int row, int col) GetOffsetInDirection(bool isEven, HexNeighborDirection direction) { switch (direction) { case HexNeighborDirection.Up: return(2, 0); case HexNeighborDirection.UpRight: return(isEven ? (1, 1) : (1, 0)); case HexNeighborDirection.DownRight: return(isEven ? (-1, 1) : (-1, 0)); case HexNeighborDirection.Down: return(-2, 0); case HexNeighborDirection.DownLeft: return(isEven ? (-1, 0) : (-1, -1)); case HexNeighborDirection.UpLeft: return(isEven ? (1, 0) : (1, -1)); } return(0, 0); }
public Hex GetNeighborAt(Index hexIndex, HexNeighborDirection direction) { (int row, int col)offsets = GetOffsetInDirection(hexIndex.row % 2 == 0, direction); return(GetHexIfInBounds(hexIndex.row + offsets.row, hexIndex.col + offsets.col)); }
public static void AddAllPossiblePawnMoves(List <FastMove> moves, FastIndex start, Team team, FastBoardNode boardNode, bool generateQuiet = true) { Team enemy = team.Enemy(); HexNeighborDirection leftAttackDir = HexNeighborDirection.UpLeft; HexNeighborDirection leftPassantDir = HexNeighborDirection.DownLeft; HexNeighborDirection rightAttackDir = HexNeighborDirection.UpRight; HexNeighborDirection rightPassantDir = HexNeighborDirection.DownRight; HexNeighborDirection forwardDir = HexNeighborDirection.Up; if (team != Team.White) { leftAttackDir = HexNeighborDirection.DownLeft; leftPassantDir = HexNeighborDirection.UpLeft; rightAttackDir = HexNeighborDirection.DownRight; rightPassantDir = HexNeighborDirection.UpRight; forwardDir = HexNeighborDirection.Down; } if (start.TryGetNeighbor(leftAttackDir, out var leftAttack)) { var leftVictim = boardNode[leftAttack]; if (leftVictim.team == enemy) { moves.Add(new FastMove(start, leftAttack, MoveType.Attack)); } if (leftVictim.team == Team.None) { if (start.TryGetNeighbor(leftPassantDir, out var leftPassant) && boardNode.PassantableIndex == leftPassant) { moves.Add(new FastMove(start, leftAttack, MoveType.EnPassant)); } } } if (start.TryGetNeighbor(rightAttackDir, out var rightAttack)) { var rightVictim = boardNode[rightAttack]; if (rightVictim.team == enemy) { moves.Add(new FastMove(start, rightAttack, MoveType.Attack)); } if (rightVictim.team == Team.None) { if (start.TryGetNeighbor(rightPassantDir, out var rightPassant) && boardNode.PassantableIndex == rightPassant) { moves.Add(new FastMove(start, rightAttack, MoveType.EnPassant)); } } } if (!generateQuiet) { return; } // One forward bool hasForward = start.TryGetNeighbor(forwardDir, out var forward); if (hasForward && !boardNode.IsOccupied(forward)) { if (forward.TryGetNeighbor(forwardDir, out var twoForward)) { moves.Add(new FastMove(start, forward, MoveType.Move)); // Two forward on 1st move if (PawnIsAtStart(team, (Index)start) && !boardNode.IsOccupied(twoForward)) { moves.Add(new FastMove(start, twoForward, MoveType.Move)); } } else { // if two squares forward doesn't exist, that means we're on the last rank for this pawn. moves.Add(new FastMove(start, forward, MoveType.Move, FastPiece.Queen)); moves.Add(new FastMove(start, forward, MoveType.Move, FastPiece.Rook)); moves.Add(new FastMove(start, forward, MoveType.Move, FastPiece.Knight)); moves.Add(new FastMove(start, forward, MoveType.Move, FastPiece.Squire)); } } }
public void UpdateEdge(HexNeighborDirection direction) => meshRenderer.material.SetFloat( name: $"_Edge{(int)direction}", value: Mathf.Abs(meshRenderer.material.GetFloat($"_Edge{(int)direction}") - 1).Floor() );
public static Index?GetNeighborAt(Index source, HexNeighborDirection dir) { return(source.GetNeighborAt(dir)); }
public static HexNeighborDirection Opposite(this HexNeighborDirection direction) => (HexNeighborDirection)(((int)direction + 3) % 6);