public bool WasCheckedBefore(List <CheckedPosition> alreadyCheckedList, CheckedPosition currentCheck) { foreach (var info in alreadyCheckedList) { if (info.Position == currentCheck.Position) { if (info.IncomeDelta == null || info.IncomeDelta == currentCheck.IncomeDelta) { return(true); } } } return(false); }
/// <summary> /// Возвращаем список всех полей, в которые можно попасть из исходного поля /// </summary> /// <param name="task"></param> /// <param name="source"></param> /// <param name="previos"></param> /// <returns></returns> public List <AvaliableMove> GetAllAvaliableMoves(GetAllAvaliableMovesTask task, TilePosition source, TilePosition previos) { Direction previosDirection; if (previos != null) { previosDirection = new Direction(previos, source); } else { previosDirection = new Direction(source, source); } var sourceTile = Map[source.Position]; var ourTeamId = task.TeamId; var ourTeam = Teams[ourTeamId]; var ourShip = ourTeam.Ship; bool fromShip = (ourShip.Position == source.Position); List <AvaliableMove> goodTargets = new List <AvaliableMove>(); IEnumerable <TilePosition> positionsForCheck; if (sourceTile.Type.RequreImmediateMove()) //для клеток с редиректами запоминаем, что в текущую клетку уже не надо возвращаться { Position previosMoveDelta = null; if (sourceTile.Type == TileType.Ice) { previosMoveDelta = previosDirection.GetDelta(); } task.alreadyCheckedList.Add(new CheckedPosition(source, previosMoveDelta)); //запоминаем, что эту клетку просматривать уже не надо } //места всех возможных ходов positionsForCheck = GetAllTargetsForSubturn(source, previosDirection, ourTeam); foreach (var newPosition in positionsForCheck) { //проверяем, что на этой клетке var newPositionTile = Map[newPosition.Position]; if (task.alreadyCheckedList.Count > 0 && previosDirection != null) { Position incomeDelta = Position.GetDelta(previosDirection.To.Position, newPosition.Position); CheckedPosition currentCheck = new CheckedPosition(newPosition, incomeDelta); if (WasCheckedBefore(task.alreadyCheckedList, currentCheck)) //мы попали по рекурсии в ранее просмотренную клетку { if ((newPositionTile.Type == TileType.Airplane) && (Map.AirplaneUsed == false)) { // даем возможность не использовать самолет сразу! goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); } continue; } } //var newMove = new Move(new TilePosition(source), new TilePosition(newPosition), MoveType.Usual); switch (newPositionTile.Type) { case TileType.Water: if (ourShip.Position == newPosition.Position) //заходим на свой корабль { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); //всегда это можем сделать if (task.NoCoinMoving == false && Map[task.FirstSource].Coins > 0) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition, true)) { MoveType = MoveType.WithCoin }); } } else if (sourceTile.Type == TileType.Water) //из воды в воду { if (source.Position != ourShip.Position && GetPosibleSwimming(task.FirstSource.Position).Contains(newPosition.Position)) //пират плавает { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); } if (source.Position == ourShip.Position && GetShipPosibleNavaigations(task.FirstSource.Position).Contains(newPosition.Position)) { //корабль плавает goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); } } else //с земли в воду мы можем попасть только если ранее попали на клетку, требующую действия { if (task.NoJumpToWater == false && sourceTile.Type.RequreImmediateMove()) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition)) { WithJumpToWater = true }); if (task.NoCoinMoving == false && Map[task.FirstSource].Coins > 0) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition)) { WithJumpToWater = true, MoveType = MoveType.WithCoin }); } } } break; case TileType.RespawnFort: if (task.FirstSource == newPosition) { if (task.NoRespawn == false && ourTeam.Pirates.Count() < 3) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition), new Respawn(ourTeam, newPosition.Position)) { MoveType = MoveType.WithRespawn }); } } else if (newPositionTile.OccupationTeamId.HasValue == false || newPositionTile.OccupationTeamId == ourTeamId) //только если форт не занят { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); } break; case TileType.Fort: if (task.NoFort == false && newPositionTile.OccupationTeamId.HasValue == false || newPositionTile.OccupationTeamId == ourTeamId) //только если форт не занят { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); } break; case TileType.Canibal: if (task.NoCanibal == false) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); } break; case TileType.Trap: if (task.NoTrap == false) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); if (task.NoCoinMoving == false && Map[task.FirstSource].Coins > 0 && (newPositionTile.OccupationTeamId == null || newPositionTile.OccupationTeamId == ourTeamId)) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition, true)) { MoveType = MoveType.WithCoin }); } } break; case TileType.Grass: case TileType.Chest1: case TileType.Chest2: case TileType.Chest3: case TileType.Chest4: case TileType.Chest5: case TileType.RumBarrel: case TileType.Spinning: goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); if (task.NoCoinMoving == false && Map[task.FirstSource].Coins > 0 && (newPositionTile.OccupationTeamId == null || newPositionTile.OccupationTeamId == ourTeamId)) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition, true)) { MoveType = MoveType.WithCoin }); } break; case TileType.Unknown: goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); break; case TileType.Horse: case TileType.Arrow: case TileType.Balloon: case TileType.Ice: case TileType.Croc: case TileType.Cannon: goodTargets.AddRange(GetAllAvaliableMoves(task, newPosition, source)); break; case TileType.Airplane: if (Map.AirplaneUsed == false) { goodTargets.AddRange(GetAllAvaliableMoves(task, newPosition, source)); } else { // если нет самолета, то клетка работает как трава! goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition))); if (task.NoCoinMoving == false && Map[task.FirstSource].Coins > 0 && (newPositionTile.OccupationTeamId == null || newPositionTile.OccupationTeamId == ourTeamId)) { goodTargets.Add(new AvaliableMove(task.FirstSource, newPosition, new Moving(task.FirstSource, newPosition, true)) { MoveType = MoveType.WithCoin }); } } break; } } return(goodTargets); }