/// <summary> /// Filters a cell for a given edge filter /// </summary> /// <param name="edgeFilter">Edge filter</param> public void FilterCell(EdgeFilter edgeFilter) { //Debug.Log($"FilterCell({edgeFilter.EdgeIndex}, {edgeFilter.FilterType.ToString()})", gameObject); if (SolvedScore == 1) { return; } var removingModules = new List <int>(); // Filter possible Modules list for a given filter for (int i = 0; i < possibleModulesIndices.Count; i++) { var module = _moduleManager.modules[possibleModulesIndices[i]]; var isImpossible = module.CheckModule(edgeFilter); if (isImpossible) { // Remove module removingModules.Add(possibleModulesIndices[i]); } } // Now remove filtered modules for (int i = 0; i < removingModules.Count; i++) { RemoveModule(removingModules[i]); } CheckSetCell(); }
/// <summary> /// Initial constraint: There can only be border on the outside. /// </summary> private void BorderOutsideConstraint() { var bottomFilter = new EdgeFilter(2, Module.EdgeConnectionTypes.Block, true); var topFilter = new EdgeFilter(0, Module.EdgeConnectionTypes.Block, true); var leftFilter = new EdgeFilter(1, Module.EdgeConnectionTypes.Block, true); var rightFilter = new EdgeFilter(3, Module.EdgeConnectionTypes.Block, true); // filter bottom and top cells for only border for (var i = 0; i < 2; i++) { var z = i * (height - 1); for (var x = 0; x < width; x++) { cells[x, z].FilterCell(i == 0 ? bottomFilter : topFilter); } } // filter left and right cells for only border for (var i = 0; i < 2; i++) { var x = i * (width - 1); for (var z = 0; z < height; z++) { cells[x, z].FilterCell(i == 0 ? leftFilter : rightFilter); } } }
/// <summary> /// Initial constraint: There can only be border on the outside /// </summary> /// <param name="cells">The grid`s cells</param> private void BorderOutsideConstraint(ref Cell[,] cells) { var edgeTypes = (Module.EdgeConnectionTypes[])Enum.GetValues(typeof(Module.EdgeConnectionTypes)); for (int i = 0; i < 2; i++) { i = (cells.GetLength(0) - 1) * i; for (int j = 0; j < cells.GetLength(1); j++) { var cell = cells[i, j]; foreach (var edgeType in edgeTypes) { if (edgeType == Module.EdgeConnectionTypes.Block) { continue; } var edgeFilter = new EdgeFilter(i == 0 ? 1 : 3, edgeType); cell.FilterCell(edgeFilter); } } } for (int j = 0; j < 2; j++) { j = (cells.GetLength(1) - 1) * j; for (int i = 0; i < cells.GetLength(0); i++) { var cell = cells[i, j]; foreach (var edgeType in edgeTypes) { if (edgeType == Module.EdgeConnectionTypes.Block) { continue; } var edgeFilter = new EdgeFilter(j == 0 ? 0 : 2, edgeType); cell.FilterCell(edgeFilter); } } } }
/// <summary> /// Checks if the removing module had the last edge type of any kind for this cell and if so populates the changes to the affected neighbour cell. /// Than removes module from <see cref="possibleModulesIndices"/> /// </summary> /// <param name="moduleIndex">Index of the removing module in <see cref="ModuleManager.modules"/></param> public void RemoveModule(int moduleIndex) { // Check module`s edge types var module = _moduleManager.modules[moduleIndex]; // Remove module from possibility space possibleModulesIndices.Remove(moduleIndex); // Update item on the heap LevelGenerator.Instance.OrderedCells.UpdateItem(this); //Debug.Log($"{gameObject.name} | RemoveModule({module.moduleGO.name})", gameObject); for (int j = 0; j < 4; j++) { // Only check if cell has a neighbour on this edge if (neighbourCells[j] == null) { continue; } var edgeType = module.edgeConnections[j]; var lastEdgeType = true; // Search in other possible modules for the same edge type for (int i = 0; i < possibleModulesIndices.Count; i++) { if (_moduleManager.modules[possibleModulesIndices[i]].edgeConnections[j] == edgeType) { lastEdgeType = false; break; } } if (lastEdgeType) { //Debug.Log($"{gameObject.name} | Last edge({j}, {edgeType.ToString()})", gameObject); // Populate edge changes to neighbour cell var edgeFilter = new EdgeFilter(j, edgeType); neighbourCells[j].FilterCell(edgeFilter); } } CheckSetCell(); }
/// <summary> /// Checks this module for a specific edge filter /// </summary> /// <param name="filter">The filter</param> /// <returns>Does this model depend on the given edge filter</returns> public bool CheckModule(EdgeFilter filter) { //Debug.Log($"Checking {moduleGO.name} for edge filter {filter.EdgeIndex}, {filter.FilterType}"); // Get receiving edge index of this module var edge = filter.EdgeIndex + 2; if (edge == 4) { edge = 0; } else if (edge == 5) { edge = 1; } // Check if module matches a given filter return(edgeConnections[edge] == filter.FilterType); }
public void SetSpecialModule(int moduleIndex) { possibleModulesIndices = new List <int> { moduleIndex }; var module = ModuleManager.Instance.modules[moduleIndex]; // Update item on the heap LevelGenerator.Instance.OrderedCells.UpdateItem(this); var edgeTypes = (Module.EdgeConnectionTypes[])Enum.GetValues(typeof(Module.EdgeConnectionTypes)); // Propagate changes to neighbours for (int i = 0; i < 4; i++) { if (neighbourCells[i] == null) { continue; } for (int j = 0; j < edgeTypes.Length; j++) { if (edgeTypes[j] != module.edgeConnections[i]) { // This edge type was removed from this edge // Populate edge changes to neighbour cell var edgeFilter = new EdgeFilter(i, edgeTypes[j]); neighbourCells[i].FilterCell(edgeFilter); } } } var newModule = Instantiate(module.moduleGO, transform.position, Quaternion.identity, transform); isCellSet = true; }
/// <summary> /// Removes a <see cref="Module"/> from <see cref="possibleModules"/> /// checking if it was the last one on any edge of a specific edge type and /// if so propagating the changes to the affected neighbour. /// </summary> /// <param name="module">The <see cref="Module"/> to remove.</param> public void RemoveModule(Module module) { // remove module from possibility space possibleModules.Remove(module); // update item on the heap levelGenerator.orderedCells.UpdateItem(this); for (var j = 0; j < neighbours.Length; j++) { // only check if cell has a neighbour on this edge if (neighbours[j] == null) { continue; } var edgeType = module.edgeConnections[j]; var lastWithEdgeType = true; // search in other possible modules for the same edge type for (var i = 0; i < possibleModules.Count; i++) { if (possibleModules[i].edgeConnections[j] == edgeType) { lastWithEdgeType = false; break; } } if (lastWithEdgeType) { // populate edge changes to neighbour cell var edgeFilter = new EdgeFilter(j, edgeType, false); neighbours[j].FilterCell(edgeFilter); } } }
/// <summary> /// Applies an <see cref="EdgeFilter"/> to this cell. /// </summary> /// <param name="filter">The filter to apply.</param> public void FilterCell(EdgeFilter filter) { if (possibleModules.Count == 1) { return; } var removingModules = new List <Module>(); // filter possible modules list for (var i = 0; i < possibleModules.Count; i++) { if (filter.CheckModule(possibleModules[i])) { removingModules.Add(possibleModules[i]); } } // remove filtered modules for (var i = 0; i < removingModules.Count; i++) { RemoveModule(removingModules[i]); } }