protected bool Equals(TilePosition other) { return(Position.Equals(other.Position) && Level == other.Level); }
public Pirate(int teamId, TilePosition position) { Id = Guid.NewGuid(); TeamId = teamId; Position = position; }
public AvaliableMove(TilePosition source, TilePosition target, params IGameAction[] actions) { Source = source; Target = target; ActionList = new GameActionList(actions); }
public Move(TilePosition from, TilePosition to, MoveType type = MoveType.Usual) : base(from, to) { Type = type; }
public TileLevel(TilePosition position) { Position = position; }
public TileLevel this[TilePosition pos] { get { return(Tiles[pos.Position.X, pos.Position.Y].Levels[pos.Level]); } }
/// <summary> /// Возвращаем все позиции, в которые в принципе достижимы из заданной клетки за один подход /// (не проверяется, допустим ли такой ход) /// </summary> /// <param name="source"></param> /// <param name="previosMove"></param> /// <returns></returns> public List <TilePosition> GetAllTargetsForSubturn(TilePosition source, Direction previosMove, Team ourTeam) { var sourceTile = Map[source.Position]; var ourShip = ourTeam.Ship; IEnumerable <TilePosition> rez; switch (sourceTile.Type) { case TileType.Horse: rez = GetHorseDeltas(source.Position) .Select(x => IncomeTilePosition(x)); break; case TileType.Cannon: rez = new [] { IncomeTilePosition(GetCannonFly(sourceTile.CannonDirection, source.Position)) }; break; case TileType.Arrow: rez = GetArrowsDeltas(sourceTile.ArrowsCode, source.Position) .Select(x => IncomeTilePosition(x)); break; case TileType.Balloon: rez = Teams.Select(x => x.Ship.Position) .Select(x => IncomeTilePosition(x)); //на корабль break; case TileType.Airplane: if (Map.AirplaneUsed == false) { var shipTargets = Teams.Select(x => x.Ship.Position) .Select(x => IncomeTilePosition(x)); //на корабль var airplaneTargets = AllTiles(x => x.Type != TileType.Water && x.Type.RequreImmediateMove() == false && x.Type != TileType.Airplane) .Select(x => x.Position) .Select(x => IncomeTilePosition(x)); rez = shipTargets.Concat(airplaneTargets); if (previosMove.From != source) { rez = rez.Concat(new [] { source }); //ход "остаемся на месте" } } else { rez = GetNearDeltas(source.Position) .Where(x => IsValidMapPosition(x)) .Where(x => Map[x].Type != TileType.Water || x == ourShip.Position) .Select(x => IncomeTilePosition(x)); } break; case TileType.Croc: rez = new[] { previosMove.From }; //возвращаемся назад break; case TileType.Ice: if (Map[previosMove.From.Position].Type == TileType.Horse) { //повторяем ход лошади rez = GetHorseDeltas(source.Position) .Select(x => IncomeTilePosition(x)); } else //повторяем предыдущий ход { //TODO - проверка на использование самолета на предыдущем ходу - тогда мы должны повторить ход самолета var previosDelta = previosMove.GetDelta(); Position target = Position.AddDelta(source.Position, previosDelta); rez = new[] { target }.Select(x => IncomeTilePosition(x)); } break; case TileType.RespawnFort: rez = GetNearDeltas(source.Position) .Where(x => IsValidMapPosition(x)) .Where(x => Map[x].Type != TileType.Water || x == ourShip.Position) .Select(x => IncomeTilePosition(x)) .Concat(new[] { source }); break; case TileType.Spinning: if (source.Level == 0) { rez = GetNearDeltas(source.Position) .Where(x => IsValidMapPosition(x)) .Where(x => Map[x].Type != TileType.Water || x == ourShip.Position) .Select(x => IncomeTilePosition(x)); } else { rez = new[] { new TilePosition(source.Position, source.Level - 1) }; } break; case TileType.Water: if (source.Position == ourShip.Position) //с своего корабля { rez = GetShipPosibleNavaigations(source.Position) .Concat(new[] { GetShipLanding(source.Position) }) .Select(x => IncomeTilePosition(x)); } else //пират плавает в воде { rez = GetPosibleSwimming(source.Position) .Select(x => IncomeTilePosition(x)); } break; default: rez = GetNearDeltas(source.Position) .Where(x => IsValidMapPosition(x)) .Where(x => Map[x].Type != TileType.Water || x == ourShip.Position) .Select(x => IncomeTilePosition(x)); break; } return(rez.Where(x => IsValidMapPosition(x.Position)).ToList()); }
/// <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); }
private void Step(TilePosition target, Pirate pirate, Ship ship, Team team) { //var moves = _availableMoves; //var actions = _actions; Tile targetTile = Board.Map[target.Position]; var source = pirate.Position.Position; Tile sourceTile = Board.Map[source]; bool onShip = (ship.Position == pirate.Position.Position); Direction direction = new Direction(pirate.Position, target); switch (targetTile.Type) { case TileType.Unknown: { // exploration if (onShip) { if (CanLanding(pirate, target)) { // landing AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Explore(target, pirate, direction), new Landing(pirate, ship), new Moving(pirate, target))); } } else { AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Explore(target, pirate, direction), new Moving(pirate, target))); } break; } case TileType.Water: { if (target == ship.Position) //на свой корабль { if (sourceTile.Coins > 0) { // shipping with coins AddMoveAndActions(new Move(pirate.Position.Position, target, MoveType.WithCoin), GameActionList.Create( new TakeCoinToShip(pirate, ship), new Shipping(pirate, ship))); } // shipping without coins AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( //new DropCoin(pirate), new Shipping(pirate, ship))); } else if (pirate.Position.Position == ship.Position) //двигаем корабль { if (((ship.Position.X == 0 || ship.Position.X == Board.Size - 1) && (target.Y <= 1 || target.Y >= Board.Size - 2)) || ((ship.Position.Y == 0 || ship.Position.Y == Board.Size - 1) && (target.X <= 1 || target.X >= Board.Size - 2))) { break; // enemy water territories } // navigation AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Navigation(ship, target))); } else if (Board.Teams.Where(x => x.Id != CurrentTeamId).Select(x => x.Ship.Position).Contains(target)) { //столкновение с чужим кораблем AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Dying(pirate))); } else //падение пирата в воду и плавание в воде { AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Moving(pirate, target))); } break; } case TileType.Chest1: case TileType.Chest2: case TileType.Chest3: case TileType.Chest4: case TileType.Chest5: case TileType.Grass: case TileType.Fort: case TileType.RespawnFort: case TileType.RumBarrel: case TileType.Canibal: case TileType.Spinning: case TileType.Trap: { var attack = targetTile.OccupationTeamId.HasValue && targetTile.OccupationTeamId.Value != pirate.TeamId; bool targetIsFort = targetTile.Type.IsFort(); //Respawn if (targetTile.Type == TileType.RespawnFort && sourceTile.Type == TileType.RespawnFort) { if (team.Pirates.Count() < 3) { AddMoveAndActions(new Move(pirate.Position.Position, target, MoveType.WithRespawn), GameActionList.Create( new Respawn(team, target))); } } if (attack) { if (targetIsFort == false) { // attack if (onShip) { if (CanLanding(pirate, target)) { AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Attack(target), new Landing(pirate, ship), new Moving(pirate, target))); } } else { AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Attack(target), new Moving(pirate, target))); } } } else { if (onShip) { if (CanLanding(pirate, target)) { AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Landing(pirate, ship), new Moving(pirate, target))); } } else { AddMoveAndActions(new Move(pirate.Position.Position, target), GameActionList.Create( new Moving(pirate, target))); if (sourceTile.Coins > 0 && targetIsFort == false) { AddMoveAndActions(new Move(pirate.Position.Position, target, MoveType.WithCoin), GameActionList.Create( new Moving(pirate, target, true))); } } } break; } } }