public void GivenЕстьСундукIdВЯчейкеСоСлучайнымЛутом(int chestId, int chestPosX, int chestPosY, Table table) { var schemeService = Context.ServiceProvider.GetRequiredService <ISchemeService>(); var sectorManager = Context.ServiceProvider.GetRequiredService <ISectorManager>(); var staticObjectManager = sectorManager.CurrentSector.StaticObjectManager; var nodeCoords = new OffsetCoords(chestPosX, chestPosY); var node = sectorManager.CurrentSector.Map.Nodes.SelectByHexCoords(nodeCoords.X, nodeCoords.Y); var dropProps = new List <IProp>(); foreach (var tableRow in table.Rows) { tableRow.TryGetValue("prop", out var propSchemeSid); tableRow.TryGetValue("count", out var resourceCount); var propScheme = schemeService.GetScheme <IPropScheme>(propSchemeSid); dropProps.Add(new Resource(propScheme, int.Parse(resourceCount))); } var dropResolverMock = new Mock <IDropResolver>(); dropResolverMock.Setup(x => x.Resolve(It.IsAny <IEnumerable <IDropTableScheme> >())) .Returns(dropProps.ToArray()); var dropResolver = dropResolverMock.Object; var chest = new DropTablePropChest(System.Array.Empty <DropTableScheme>(), dropResolver); var staticObject = new StaticObject(node, chest.Purpose, chestId); staticObject.AddModule <IPropContainer>(chest); staticObjectManager.Add(staticObject); }
private bool TryRollInteriorCoord(OffsetCoords[] openCoords, IEnumerable <OffsetCoords> passableRegionCoords, bool checkPass, out OffsetCoords rolledCoords) { var supposedRolledCoords = _dice.RollFromList(openCoords); if (!checkPass) { rolledCoords = supposedRolledCoords; return(true); } // Проверяем, что элемент декора не перекрывает проход. var isNotBlockPass = CheckMapPassable(passableRegionCoords, supposedRolledCoords); if (!isNotBlockPass) { rolledCoords = supposedRolledCoords; return(false); } rolledCoords = supposedRolledCoords; return(true); }
public void GivenЕстьСундукIdВЯчейкеСоСлучайнымЛутом(int chestId, int chestPosX, int chestPosY, Table table) { var schemeService = Context.Container.GetInstance <ISchemeService>(); var containerManager = Context.Container.GetInstance <IPropContainerManager>(); var sectorManager = Context.Container.GetInstance <ISectorManager>(); var nodeCoords = new OffsetCoords(chestPosX, chestPosY); var node = sectorManager.CurrentSector.Map.Nodes.Cast <HexNode>().SelectBy(nodeCoords.X, nodeCoords.Y); var dropProps = new List <IProp>(); foreach (var tableRow in table.Rows) { tableRow.TryGetValue("prop", out var propSchemeSid); tableRow.TryGetValue("count", out var resourceCount); var propScheme = schemeService.GetScheme <IPropScheme>(propSchemeSid); dropProps.Add(new Resource(propScheme, int.Parse(resourceCount))); } var dropResolverMock = new Mock <IDropResolver>(); dropResolverMock.Setup(x => x.Resolve(It.IsAny <IEnumerable <IDropTableScheme> >())) .Returns(dropProps.ToArray()); var dropResolver = dropResolverMock.Object; var chest = new DropTablePropChest(node, new DropTableScheme[0], dropResolver, chestId); containerManager.Add(chest); }
public void AddHumanActor(string personSid, OffsetCoords startCoords) { var playerState = Container.GetInstance <IPlayerState>(); var schemeService = Container.GetInstance <ISchemeService>(); var sector = Container.GetInstance <ISector>(); var humanTaskSource = Container.GetInstance <IHumanActorTaskSource>(); var actorManager = Container.GetInstance <IActorManager>(); var personScheme = schemeService.GetScheme <PersonScheme>(personSid); // Подготовка актёров var humanStartNode = sector.Map.Nodes.Cast <HexNode>().SelectBy(startCoords.X, startCoords.Y); var humanActor = CreateHumanActor(_humanPlayer, personScheme, humanStartNode); humanTaskSource.SwitchActor(humanActor); actorManager.Add(humanActor); var humanActroViewModelMock = new Mock <IActorViewModel>(); humanActroViewModelMock.SetupGet(x => x.Actor).Returns(humanActor); var humanActroViewModel = humanActroViewModelMock.Object; playerState.ActiveActor = humanActroViewModel; }
public void AddHumanActor(string personSid, ISector sector, OffsetCoords startCoords) { if (sector is null) { throw new ArgumentNullException(nameof(sector)); } var humanPlayer = ServiceProvider.GetRequiredService <IPlayer>(); var playerState = ServiceProvider.GetRequiredService <ISectorUiState>(); var actorManager = sector.ActorManager; var perkResolver = ServiceProvider.GetRequiredService <IPerkResolver>(); // Подготовка актёров var humanStartNode = sector.Map.Nodes.SelectByHexCoords(startCoords.X, startCoords.Y); var humanActor = CreateHumanActor(personSid, humanStartNode, perkResolver); humanPlayer.BindPerson(Globe, humanActor.Person); actorManager.Add(humanActor); var humanActroViewModelMock = new Mock <IActorViewModel>(); humanActroViewModelMock.SetupGet(x => x.Actor).Returns(humanActor); var humanActroViewModel = humanActroViewModelMock.Object; playerState.ActiveActor = humanActroViewModel; }
public void RollInteriorObjectsTest() { const int SQARE_SIZE = 12; // ARRANGE var diceMock = new Mock <IDice>(); diceMock.Setup(x => x.Roll(It.IsAny <int>())).Returns(1); var dice = diceMock.Object; var interiorRandomSource = new InteriorObjectRandomSource(dice); var coords = new OffsetCoords[SQARE_SIZE * SQARE_SIZE]; for (var i = 0; i < SQARE_SIZE; i++) { for (var j = 0; j < SQARE_SIZE; j++) { coords[i + (j * SQARE_SIZE)] = new OffsetCoords(i, j); } } // ACT var factMetas = interiorRandomSource.RollInteriorObjects(coords, true); // ASSERT factMetas.Should().NotBeEmpty(); }
/// <summary> /// Выполняет заливку области в поле шестиугольников с учётом размера в 7 узлов. /// </summary> /// <param name="matrix"> Поле шестиугольников. Будут заливаться ячейки со сзначением <b>true</b>. </param> /// <param name="point"> Точка, с которой начинается заливка. Должна указывать на ячейку со значением <b>true</b>. </param> /// <returns> Возвращает точки, которые были залиты. </returns> public static IEnumerable <OffsetCoords> FloodFill7(Matrix <bool> matrix, OffsetCoords point) { return(FloodFillInner( matrix, point, nextCoords => CheckAvailableFor7(nextCoords, matrix))); }
private static void HandleMoveCommand( IServiceScope serviceScope, ISectorUiState uiState, ICommandPool commandManager, ISectorNode playerActorSectorNode, string inputText) { var components = inputText.Split(' '); var x = int.Parse(components[1], CultureInfo.InvariantCulture); var y = int.Parse(components[2], CultureInfo.InvariantCulture); var offsetCoords = new OffsetCoords(x, y); ISectorMap map = playerActorSectorNode.Sector.Map; var targetNode = map.Nodes.OfType <HexNode>() .SingleOrDefault(node => node.OffsetCoords == offsetCoords); var command = serviceScope.ServiceProvider.GetRequiredService <MoveCommand>(); uiState.SelectedViewModel = new NodeViewModel { Node = targetNode }; PushCommandToExecution(commandManager, command); }
public static OffsetCoords GetFreeCell(RoomMatrix grid, OffsetCoords rolled) { for (var i = 0; i < grid.Size; i++) { for (var j = 0; j < grid.Size; j++) { if (IsValidForRoom(grid, rolled, i, j, 1, 1)) { return(new OffsetCoords(rolled.X + i * 1, rolled.Y + j * 1)); } if (IsValidForRoom(grid, rolled, i, j, -1, 1)) { return(new OffsetCoords(rolled.X + i * -1, rolled.Y + j * 1)); } if (IsValidForRoom(grid, rolled, i, j, 1, -1)) { return(new OffsetCoords(rolled.X + i * 1, rolled.Y + j * -1)); } if (IsValidForRoom(grid, rolled, i, j, -1, -1)) { return(new OffsetCoords(rolled.X + i * -1, rolled.Y + j * -1)); } } } return(null); }
/// <summary> /// Преобразовывет черновые регионы в узлы реальной карты. /// </summary> private static void MapDraftRegionsToSectorMap(Matrix <bool> matrix, RegionDraft[] draftRegions, ISectorMap map) { var cellMap = matrix.Items; var mapWidth = matrix.Width; var mapHeight = matrix.Height; var regionNodeCoords = draftRegions.SelectMany(x => x.Coords); var hashSet = new HashSet <OffsetCoords>(regionNodeCoords); for (var x = 0; x < mapWidth; x++) { for (var y = 0; y < mapHeight; y++) { if (cellMap[x, y]) { var offsetCoord = new OffsetCoords(x, y); if (!hashSet.Contains(offsetCoord)) { var node = new HexNode(x, y); map.AddNode(node); } } } } }
//TODO Попробовать сделать загрузку всех провинций параллельно. // Выглядит так, что каждый запуск метода не зависит от предыдущих запусков. /// <summary> /// Создание соседних провинций. /// </summary> /// <param name="playerCoords"> Текущии координаты игрока. </param> /// <param name="worldManager"> Менеджер мира. </param> /// <param name="worldGenerator"> Генератор мира, используемый для создания новых провинций. </param> /// <returns> Возвращает объект Task. </returns> private static async System.Threading.Tasks.Task CreateNeighborRegionsAsync(OffsetCoords playerCoords, IWorldManager worldManager, IWorldGenerator worldGenerator, ProgressStorageService progressStorageService) { for (var offsetX = -1; offsetX <= 1; offsetX++) { for (var offsetY = -1; offsetY <= 1; offsetY++) { if (offsetX == 0 && offsetY == 0) { // Это нулевое смещение от текущего элемента. // Пропускаем, т.к. текущий элемент уже есть. continue; } var terrainX = playerCoords.X + offsetX; var terrainY = playerCoords.Y + offsetY; if (worldManager.Globe.Terrain.GetLowerBound(0) <= terrainX && terrainX <= worldManager.Globe.Terrain.GetUpperBound(0) && worldManager.Globe.Terrain[0].GetLowerBound(0) <= terrainY && terrainY <= worldManager.Globe.Terrain[0].GetUpperBound(0)) { var terrainCell = worldManager.Globe.Terrain[terrainX][terrainY]; if (!worldManager.Regions.ContainsKey(terrainCell)) { var createdNeiborRegion = await CreateRegionAsync(worldManager.Globe, terrainCell, worldGenerator, progressStorageService); worldManager.Regions[terrainCell] = createdNeiborRegion; } } } } }
public static bool IsAvailableFor7(Matrix <bool> matrix, OffsetCoords coords) { if (matrix is null) { throw new ArgumentNullException(nameof(matrix)); } if (!IsAvailableFor(matrix, coords)) { return(false); } var neighbors = HexHelper.GetNeighbors(coords.X, coords.Y); foreach (var neightbor in neighbors) { if (!matrix.IsIn(neightbor.X, neightbor.Y)) { return(false); } if (!matrix[neightbor.X, neightbor.Y]) { return(false); } } return(true); }
private static void HandleMoveCommand(IServiceScope serviceScope, ISectorUiState uiState, ISectorNode playerActorSectorNode, string inputText) { var components = inputText.Split(' '); var x = int.Parse(components[1], CultureInfo.InvariantCulture); var y = int.Parse(components[2], CultureInfo.InvariantCulture); var offsetCoords = new OffsetCoords(x, y); ISectorMap map = playerActorSectorNode.Sector.Map; var targetNode = map.Nodes.OfType <HexNode>() .SingleOrDefault(node => node.OffsetCoords == offsetCoords); var command = serviceScope.ServiceProvider.GetRequiredService <MoveCommand>(); uiState.SelectedViewModel = new NodeViewModel { Node = targetNode }; if (command.CanExecute()) { command.Execute(); } else { Console.WriteLine(UiResource.CommandCantExecuteMessage); } }
public bool IsHexValid(Hex hex) { OffsetCoords o = CubeToOffset(HexToCube(hex)); bool valid = (o.row >= 0 && o.row <= (rows - 1) && o.column >= 0 && o.column <= (columns - 1)); return(valid); }
public OffsetCoords HexToOffset(Hex hex) { Cube cube = HexToCube(hex); OffsetCoords coords = CubeToOffset(cube); return(coords); }
/// <summary> /// Соединяет две комнаты коридором. /// </summary> /// <param name="map"> Карта, над которой идёт работа. </param> /// <param name="room"> Комната, которую соединяем. </param> /// <param name="selectedRoom"> Целевая комната для соединения. </param> /// <param name="edgeHash"> Хэш рёбер (для оптимизации). </param> protected static void ConnectRoomsWithCorridor(IMap map, Room room, Room selectedRoom, HashSet <string> edgeHash) { if (room is null) { throw new System.ArgumentNullException(nameof(room)); } if (selectedRoom is null) { throw new System.ArgumentNullException(nameof(selectedRoom)); } var currentNode = GetRoomCenterNode(room); var targetNode = GetRoomCenterNode(selectedRoom); var points = CubeCoordsHelper.CubeDrawLine(currentNode.CubeCoords, targetNode.CubeCoords); foreach (var point in points) { var offsetCoords = HexHelper.ConvertToOffset(point); // Это происходит, потому что если при нулевом Х для обеих комнат // попытаться отрисовать линию коридора, то она будет змейкой заходить за 0. // Нужно искать решение получше. offsetCoords = new OffsetCoords(offsetCoords.X < 0 ? 0 : offsetCoords.X, offsetCoords.Y < 0 ? 0 : offsetCoords.Y); var node = RoomHelper.CreateCorridorNode(map, edgeHash, currentNode, offsetCoords.X, offsetCoords.Y); currentNode = node; } }
public void GetNeighborNodes_NodeFromTopLeftCorner_NodesFromFourSegments() { // ARRANGE const int segmentSize = 4; var map = new LazyHexMap(segmentSize); var zeroOffset = new OffsetCoords(0, 0); var zeroNode = map.Nodes.Single(x => x.Offset.Equals(zeroOffset)); // ACT var nodes = map.GetNeighborNodes(zeroNode); var nodeArray = nodes.ToArray(); // ASSERT nodeArray[0].Offset.Should().Be(new OffsetCoords(-1, 0)); nodeArray[1].Offset.Should().Be(new OffsetCoords(-1, 1)); nodeArray[2].Offset.Should().Be(new OffsetCoords(0, 1)); nodeArray[3].Offset.Should().Be(new OffsetCoords(1, 0)); nodeArray[4].Offset.Should().Be(new OffsetCoords(0, -1)); nodeArray[5].Offset.Should().Be(new OffsetCoords(-1, -1)); }
HexCell GetHexCell(Hex hex) { OffsetCoords o = CubeToOffset(HexToCube(hex)); GameObject thisHex = hexArray[o.column, o.row]; HexCell hexCell = thisHex.GetComponent <HexCell>(); return(hexCell); }
public static OffsetCoords GetOffsetCoords(int x, int y, int z) { OffsetCoords convertedCoords = new OffsetCoords(); convertedCoords.col = x + (int)((z - (z & 1)) / 2); convertedCoords.row = z; return(convertedCoords); }
/// <summary> /// Выполняет заливку области в поле шестиугольников. /// </summary> /// <param name="matrix"> Поле шестиугольников. Будут заливаться ячейки со сзначением <b>true</b>. </param> /// <param name="point"> Точка, с которой начинается заливка. Должна указывать на ячейку со значением <b>true</b>. </param> /// <returns> Возвращает точки, которые были залиты. </returns> public static IEnumerable <OffsetCoords> FloodFill(Matrix <bool> matrix, OffsetCoords point) { if (matrix is null) { throw new ArgumentNullException(nameof(matrix)); } var snapshotCellmap = (bool[, ])matrix.Items.Clone(); var regionPoints = new List <OffsetCoords>(); var openPoints = new HashSet <OffsetCoords> { point }; while (openPoints.Count > 0) { var currentCell = openPoints.First(); openPoints.Remove(currentCell); var isInBound = IsInBounds(currentCell, matrix.Width, matrix.Height); if (!isInBound) { // Если текущая точка указывает за край карты, то не пытаемся её заливать. // Пропускаем. continue; } if (!snapshotCellmap[currentCell.X, currentCell.Y]) { // Заливаем только живые клетки. // Мертвые клетки являются границей, они не попадают в заливку. continue; } regionPoints.Add(currentCell); snapshotCellmap[currentCell.X, currentCell.Y] = false; var cubeCoords = HexHelper.ConvertToCube(currentCell); var clockwiseOffsets = HexHelper.GetOffsetClockwise(); foreach (var offset in clockwiseOffsets) { var neighbourCubeCoords = cubeCoords + offset; var neighbourCoords = HexHelper.ConvertToOffset(neighbourCubeCoords); if (!openPoints.Contains(neighbourCoords)) { openPoints.Add(neighbourCoords); } } } return(regionPoints); }
public HexNode(OffsetCoords coords) { OffsetCoords = coords; var x = coords.X; var y = coords.Y; CubeCoords = HexHelper.ConvertToCube(x, y); }
// TODO: fix this so that it calculates around the world properly. public int HexDistance(Hex a, Hex b) { OffsetCoords fullOffset = new OffsetCoords(columns, 0); Hex b2 = OffsetToHex(HexToOffset(b) + fullOffset); Hex b3 = OffsetToHex(HexToOffset(b) - fullOffset); int dist = System.Math.Min(System.Math.Min(Hex.Distance(a, b), Hex.Distance(a, b2)), Hex.Distance(a, b3)); return(dist); }
public override bool Equals(object obj) { WorldTile otherTile = obj as WorldTile; if (otherTile == null) { return(false); } return(OffsetCoords.Equals(otherTile.OffsetCoords)); }
public void ConvertToOffsetTest(int offsetX, int offsetY, int cubeX, int cubeY, int cubeZ) { // ARRANGE var cubeCoords = new CubeCoords(cubeX, cubeY, cubeZ); var expectedOffset = new OffsetCoords(offsetX, offsetY); // ACT var factOffsetCoords = HexHelper.ConvertToOffset(cubeCoords); // ASSERT factOffsetCoords.Should().BeEquivalentTo(expectedOffset); }
public void Restore(HumanPlayer humanPlayer, Globe globe, IWorldManager worldManager) { var terrainCoords = new OffsetCoords(TerrainX, TerrainY); var terrainCell = globe.Terrain.SelectMany(x => x).Single(x => x.Coords == terrainCoords); humanPlayer.Terrain = terrainCell; humanPlayer.SectorSid = SectorSid; var globeRegion = worldManager.Regions[terrainCell]; humanPlayer.GlobeNode = globeRegion.RegionNodes.Single(x => x.OffsetX == CurrentGlobeNodeX && x.OffsetY == CurrentGlobeNodeY); }
public IPropContainer AddChest(int id, OffsetCoords nodeCoords) { var containerManager = Container.GetInstance <IPropContainerManager>(); var sector = Container.GetInstance <ISector>(); var node = sector.Map.Nodes.Cast <HexNode>().SelectBy(nodeCoords.X, nodeCoords.Y); var chest = new FixedPropChest(node, new IProp[0], id); containerManager.Add(chest); return(chest); }
public void ThenАктёрНаходитсяВЯчейке(int expectedOffsetX, int expectedOffsetY) { var actor = Context.GetActiveActor(); var node = actor.Node; var hexNode = (HexNode)node; var expectedOffsetCoords = new OffsetCoords(expectedOffsetX, expectedOffsetY); var factOffsetCoords = hexNode.OffsetCoords; factOffsetCoords.Should().Be(expectedOffsetCoords); }
/// <summary> /// Выбрасывает случайный набор уникальных координат в матрице комнат указаной длины. /// </summary> /// <param name="roomGridSize">Размер матрицы комнат.</param> /// <param name="roomCount">Количество комнат в секторе.</param> /// <returns> /// Возвращает массив координат из матрицы комнат. /// </returns> public IEnumerable <OffsetCoords> RollRoomMatrixPositions(int roomGridSize, int roomCount) { var result = new OffsetCoords[20]; for (var y = 0; y < 4; y++) { for (var x = 0; x < 5; x++) { result[x + y * 5] = new OffsetCoords(x, y); } } return(result); }
private static bool IsInBounds(OffsetCoords coords, int width, int height) { if (!ValueInRange(value: coords.X, min: 0, max: width - 1)) { return(false); } if (!ValueInRange(value: coords.Y, min: 0, max: height - 1)) { return(false); } return(true); }
public static bool IsAvailableFor(Matrix <bool> matrix, OffsetCoords coords) { if (matrix is null) { throw new ArgumentNullException(nameof(matrix)); } if (!matrix[coords.X, coords.Y]) { return(false); } return(true); }