public static bool AxisAligned(IList <Hex> hexes, Position direction) { if (null == hexes || hexes.Count < 2) { return(true); } Hex directionHex = Neighborhood.GetDirectionHex(direction); Hex directionOppositeHex = Neighborhood.GetDirectionHex(Neighborhood.GetOpposite(direction)); return(hexes.Skip(1).All(h => AxisAligned(hexes[0], h) && (DirectionHex(hexes[0], h) == directionHex || DirectionHex(hexes[0], h) == directionOppositeHex) )); }
public static bool IsCongruent(Board board1, Board board2) { if (!EqualPiecesInPlay(board1, board2)) { return(false); } // check reflection congruence for (int i = 1; i <= 6; i++) { bool isCongruent = true; foreach (Cell cell in board1._cellMap.Values) { if (cell.Piece != board2._cellMap[Neighborhood.MirrorOriginHex(cell.hex, i)].Piece) { isCongruent = false; break; } } if (isCongruent) { return(true); } } // check rotational congruence for (int i = 1; i < 6; i++) { bool isCongruent = true; foreach (Cell cell in board1._cellMap.Values) { if (cell.Piece != board2._cellMap[Neighborhood.Rotate60DegreesClockwiseHex(cell.hex, i)].Piece) { isCongruent = false; break; } } if (isCongruent) { return(true); } } return(false); }
public void PostProcessHandler(object sender, EventArgs e) { _extendedRunsOfFour = new List <CellRun>(); foreach (CellRun run in RunsOfFourOrMore) { Cell end1 = run.First; Cell end2 = run.Last; Position direction2 = Neighborhood.GetDirection(end1.hex, end2.hex); Position direction1 = Neighborhood.GetDirection(end2.hex, end1.hex); Cell currentCell = end1.NeighborhoodCells[direction1]; List <Cell> cellList = new List <Cell>(run.Run); while (!(currentCell is Wall) && currentCell.Piece.Color != PieceColor.None) { cellList.Add(currentCell); currentCell = currentCell.NeighborhoodCells[direction1]; } // now go the other way currentCell = end2.NeighborhoodCells[direction2]; while (!(currentCell is Wall) && currentCell.Piece.Color != PieceColor.None) { cellList.Add(currentCell); currentCell = currentCell.NeighborhoodCells[direction2]; } _extendedRunsOfFour.Add(new CellRun(cellList)); } // track intersectons HashSet <Hex> hexesInRuns = new HashSet <Hex>(); _extendedRunsOfFour.All(l => l.Run.All((c) => { if (hexesInRuns.Contains(c.hex)) { _intersections.Add(c); } else { hexesInRuns.Add(c.hex); } return(true); } )); }
public RemoveMovePart(IEnumerable <Hex> removeList) { _hexesToRemove = removeList.ToList(); _direction = Neighborhood.GetDirection(_hexesToRemove.First(), _hexesToRemove.Last()); }
public static void LinkCells(Cell from, Cell to, Position pos) { from.neighborhood[pos] = to; to.neighborhood[Neighborhood.GetOpposite(pos)] = from; }
/* * private void AddPossibleMoves(List<Hex> removeBeforeList, Board prePushRemovedBoard, Hex wallHex, Position pos, bool isGipf) * { * Board pushBoard = prePushRemovedBoard.Clone(); * Wall pWall = (Wall)pushBoard.Cells[wallHex]; * * pWall.Push(pos, new GipfPiece(isGipf ? 2 : 1, colorToPlay)); * pushBoard.FindRuns(); * pushBoard.CalculateAllPossibleRemoveLists(); * * foreach (IReadOnlyList<Hex> removeAfterList in pushBoard.AllPossibleRemoveLists) * { * Move move = new Move(pWall.hex, pWall.NeighborhoodCells[pos].hex, removeBeforeList.ToList(), removeAfterList.ToList(), isGipf); * move.SimplifyMove(prePushRemovedBoard); * _moves.Add(move); * } * } */ /// <summary> /// Make a move. Validates the move or fails. /// </summary> /// <param name="move"></param> public bool TryMakeMove(Move move) { try { if (_gameResult != GameResult.Incomplete) { throw new Exception("This game is over"); } if (false == _canPlayGipf[(int)ColorToPlay] && move.isGipf) { throw new Exception("Cannot play a Gipf piece at this time"); } GipfPiece piece = Pieces.GetPiece(this, move); Position direction = Neighborhood.GetDirection(move.from, move.to); if (move.isPlacement) { if (_cellMap[move.to].Piece.Color != PieceColor.None) { throw new Exception($"Trying to place on top of an existing piece: {move.to.column}, {move.to.row}"); } } else { if (!(_cellMap[move.from] is Wall)) { throw new Exception($"Trying to push from a non-wall: {move.from.column}, {move.from.row} => {direction}"); } if (!_cellMap[move.from].CanPush(direction)) { throw new Exception($"Cannot push here: {move.from.column}, {move.from.row} => {direction}"); } } RemoveOrCapturePieces(move.removeBefore); // TODO if the run of four is all gipf, do not throw an exception if (ExtendedRunsOfFour.Count != 0) { throw new Exception("Pre-push removal did not clear all extended runs of four"); } if (move.isPlacement) { _cellMap[move.to].SetPiece(piece); } else { _cellMap[move.from].Push(direction, piece); } _runsDirty = true; RemoveFromReserve(piece.Color, piece.NumPieces); RemoveOrCapturePieces(move.removeAfter); if (ExtendedRunsOfFour.Count(r => r.Color == ColorToPlay) != 0) { throw new Exception($"Post-push removal did not clear all extended runs of four of current player's color ({ColorToPlay})"); } if (!move.isGipf) { _canPlayGipf[(int)ColorToPlay] = false; } _movesDirty = true; IncrementTurn(); return(true); } catch (Exception ex) { _lastError = ex.Message; return(false); } }