public double?DistanceTo(Position to) { //Если уже подсчитали CalcPosition res; if (_isComplete || (_calculated.TryGetValue(to, out res) && res.IsShortestDistance(_unknownSteps))) { return(Distance(to)); } do { var newPos = new List <CalcPosition>(); foreach (var pos in _lastCalculatedStep) { _lastCalculatedStepNumber++; var position = pos; //TODO: Вызывать правильную функцию GetAllAvaliableMoves с результатами которые отдаются плеерам для хода //TODO: если нужны только ходы с золотом - из результатов убирать ходы без золота //Не проверяем ходы до клеток, до которых уже просчитали самые короткие маршруты var checkedPositions = _calculated.Where(c => c.Value.IsShortestDistance(_unknownSteps)).Select(c => new CheckedPosition(new TilePosition(c.Value.Position))).ToList(); var task = new GetAllAvaliableMovesTask(); task.TeamId = _teamId; task.alreadyCheckedList = new List <CheckedPosition>(checkedPositions); task.FirstSource = new TilePosition(position.Position); task.NoJumpToWater = true; task.NoCanibal = true; var avaliableMoves = _board.GetAllAvaliableMoves(task); newPos.AddRange(avaliableMoves .Select(p => new CalcPosition(position.Distance + position.SelfDistance(_board, _unknownSteps), p.Target.Position, _lastCalculatedStepNumber)) .ToList()); } _lastCalculatedStep = AddStepPositions(newPos); if (!_lastCalculatedStep.Any()) { _isComplete = true; break; } //Если уже нашли дистанцию - останавливаемся if (_calculated.TryGetValue(to, out res) && res.IsShortestDistance(_unknownSteps)) { return(Distance(to)); } } while (true); return(Distance(to)); }
private void GetAvailableMoves(int teamId) { _availableMoves.Clear(); _actions.Clear(); Team team = Board.Teams[teamId]; Ship ship = team.Ship; IEnumerable <Pirate> activePirates; Direction previosDirection = null; if (NeedSubTurnPirate != null) { activePirates = new[] { NeedSubTurnPirate }; previosDirection = PreviosSubTurnDirection; } else { activePirates = team.Pirates.Where(x => x.IsDrunk == false && x.IsInTrap == false); } var targets = new List <AvaliableMove>(); foreach (var pirate in activePirates) { var position = pirate.Position; GetAllAvaliableMovesTask task = new GetAllAvaliableMovesTask(); task.TeamId = teamId; task.FirstSource = position; task.PreviosSource = (previosDirection != null) ? previosDirection.From : null; List <AvaliableMove> temp = Board.GetAllAvaliableMoves(task); targets.AddRange(temp); } //если есть ходы, которые не приводят к прыжку в воду, то выбираем только их if (targets.Any(x => x.WithJumpToWater == false)) { targets = targets.Where(x => x.WithJumpToWater == false).ToList(); } foreach (AvaliableMove avaliableMove in targets) { Move move = new Move(avaliableMove.Source, avaliableMove.Target, avaliableMove.MoveType); GameActionList actionList = avaliableMove.ActionList; AddMoveAndActions(move, actionList); } }
/// <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); }
public List <AvaliableMove> GetAllAvaliableMoves(GetAllAvaliableMovesTask task) { return(GetAllAvaliableMoves(task, task.FirstSource, task.PreviosSource)); }