Beispiel #1
0
        /// <summary>Override; see base.</summary>
        public override ConstraintResult Process(SolverState state)
        {
            if (state.LastPlacedCell == null)
            {
                return(null);
            }

            var unknowns = AffectedCells.Count(af => state[af] == null);

            if (unknowns != 1)
            {
                return(null);
            }
            var unknown = AffectedCells.First(af => state[af] == null);

            state.MarkImpossible(unknown, value => !IsValid(
                                     state[AffectedCells[0]] ?? value,
                                     state[AffectedCells[1]] ?? value,
                                     state[AffectedCells[2]] ?? value,
                                     state[AffectedCells[3]] ?? value,
                                     state[AffectedCells[4]] ?? value,
                                     state[AffectedCells[5]] ?? value
                                     ));
            return(null);
        }
 /// <summary>Override; see base.</summary>
 public override ConstraintResult Process(SolverState state)
 {
     if (state.LastPlacedCell == null)
     {
         return(null);
     }
     foreach (var parity in _parities)
     {
         var count = AffectedCells.Count(cell => state[cell] != null && state[cell].Value % 2 == parity);
         if (count == AffectedCells.Length / 2)
         {
             foreach (var cell in AffectedCells)
             {
                 if (state[cell] == null)
                 {
                     for (var v = state.MinValue; v <= state.MaxValue; v++)
                     {
                         if (v % 2 == parity)
                         {
                             state.MarkImpossible(cell, v);
                         }
                     }
                 }
             }
         }
     }
     return(null);
 }
        public override bool Verify(int[] grid)
        {
            var p1 = AffectedCells.IndexOf(ix => grid[ix] == Digit1);
            var p2 = AffectedCells.IndexOf(ix => grid[ix] == Digit2);

            if (p1 == -1 || p2 == -1)
            {
                return(false);
            }
            return(AffectedCells.Skip(p1 + 1).Take(p2 - 1 - 1).Sum(ix => grid[ix]) == Clue);
        }
Beispiel #4
0
        /// <summary>Override; see base.</summary>
        public override ConstraintResult Process(SolverState state)
        {
            if (state.LastPlacedCell != null && !AffectedCells.Contains(state.LastPlacedCell.Value))
            {
                return(null);
            }

            var innerTakens = new bool[Subconstraints.Length][][];
            List <Constraint> newSubconstraints = null;

            for (var sc = 0; sc < Subconstraints.Length; sc++)
            {
                var substate = new SolverStateImpl {
                    Parent = state, Takens = Ut.NewArray <bool>(state.GridSize, state.MaxValue - state.MinValue + 1)
                };
                var result = Subconstraints[sc].Process(substate);
                innerTakens[sc] = substate.Takens;

                if (result is ConstraintReplace)
                {
                    throw new NotImplementedException("The OrConstraint does not support subconstraints that replace themselves with new constraints.");
                }
                else if (result is ConstraintViolation)
                {
                    if (newSubconstraints == null)
                    {
                        newSubconstraints = new List <Constraint>(Subconstraints.Take(sc));
                    }
                }
                else if (newSubconstraints != null)
                {
                    newSubconstraints.Add(Subconstraints[sc]);
                }
            }

            foreach (var cell in AffectedCells)
            {
                state.MarkImpossible(cell, value => innerTakens.All(taken => taken == null || taken[cell][value - state.MinValue]));
            }

            if (newSubconstraints != null)
            {
                return new[] { new OrConstraint(newSubconstraints) }
            }
            ;
            return(null);
        }
    }
Beispiel #5
0
 /// <summary>Override; see base.</summary>
 public override ConstraintResult Process(SolverState state)
 {
     if (state.LastPlacedCell != null)
     {
         var i = AffectedCells.IndexOf(state.LastPlacedCell.Value);
         var v = state.LastPlacedValue;
         state.MarkImpossible(AffectedCells[((i + v) % AffectedCells.Length + AffectedCells.Length) % AffectedCells.Length], v);
         state.MarkImpossible(AffectedCells[((i - v) % AffectedCells.Length + AffectedCells.Length) % AffectedCells.Length], v);
     }
     else
     {
         for (var i = 0; i < AffectedCells.Length; i++)
         {
             state.MarkImpossible(AffectedCells[i], v => (i + v) % AffectedCells.Length == i);
         }
     }
     return(null);
 }
Beispiel #6
0
        /// <summary>Override; see base.</summary>
        public override ConstraintResult Process(SolverState state)
        {
            if (state.LastPlacedCell == null)
            {
                return(null);
            }

            var unknowns = AffectedCells.Count(af => state[af] == null);

            if (unknowns == 1)
            {
                var unknown = AffectedCells.First(af => state[af] == null);

                state.MarkImpossible(unknown, value => !IsValid(
                                         state[AffectedCells[0]] ?? value,
                                         state[AffectedCells[1]] ?? value,
                                         state[AffectedCells[2]] ?? value,
                                         state[AffectedCells[3]] ?? value
                                         ));
            }
            else if (unknowns == 2)
            {
                var unkn1     = AffectedCells.First(af => state[af] == null);
                var unkn1Ix   = AffectedCells.IndexOf(unkn1);
                var unkn2     = AffectedCells.Last(af => state[af] == null);
                var numValues = state.MaxValue - state.MinValue + 1;
                var possibles = new bool[numValues * numValues];
                for (var val1 = state.MinValue; val1 <= state.MaxValue; val1++)
                {
                    for (var val2 = state.MinValue; val2 <= state.MaxValue; val2++)
                    {
                        possibles[(val1 - state.MinValue) + numValues * (val2 - state.MinValue)] = IsValid(
                            state[AffectedCells[0]] ?? (unkn1Ix == 0 ? val1 : val2),
                            state[AffectedCells[1]] ?? (unkn1Ix == 1 ? val1 : val2),
                            state[AffectedCells[2]] ?? (unkn1Ix == 2 ? val1 : val2),
                            state[AffectedCells[3]] ?? (unkn1Ix == 3 ? val1 : val2));
                    }
                }
                state.MarkImpossible(unkn1, value1 => Enumerable.Range(0, numValues).All(value2 => !possibles[(value1 - state.MinValue) + numValues * value2]));
                state.MarkImpossible(unkn2, value2 => Enumerable.Range(0, numValues).All(value1 => !possibles[value1 + numValues * (value2 - state.MinValue)]));
            }

            return(null);
        }
Beispiel #7
0
        protected override bool InternalApply()
        {
            var containedTraps = Fight.GetTriggers().OfType <Trap>().Where(entry => entry.VisibleState == GameActionFightInvisibilityStateEnum.INVISIBLE &&
                                                                           Caster.IsEnnemyWith(entry.Caster) &&
                                                                           AffectedCells.Contains(entry.Shape.Cell));

            foreach (var trap in containedTraps)
            {
                trap.VisibleState = GameActionFightInvisibilityStateEnum.VISIBLE;
                ContextHandler.SendGameActionFightMarkCellsMessage(Fight.Clients, trap);
            }

            foreach (var target in GetAffectedActors().Where(target => target.VisibleState == GameActionFightInvisibilityStateEnum.INVISIBLE && target.IsEnnemyWith(Caster)))
            {
                target.SetInvisibilityState(GameActionFightInvisibilityStateEnum.VISIBLE);
            }

            return(true);
        }
Beispiel #8
0
        /// <summary>Override; see base.</summary>
        public override ConstraintResult Process(SolverState state)
        {
            var minPossibleSum = AffectedCells.Sum(state.MinPossible);
            var maxPossibleSum = AffectedCells.Sum(state.MaxPossible);

            for (var ix = 0; ix < AffectedCells.Length; ix++)
            {
                var cell = AffectedCells[ix];
                if (state[cell] != null)
                {
                    continue;
                }
                var minOther = minPossibleSum - state.MinPossible(cell);
                var maxOther = maxPossibleSum - state.MaxPossible(cell);
                state.MarkImpossible(cell, value => minOther + value > Sum || maxOther + value < Sum);
            }

            return(null);
        }
        /// <summary>Override; see base.</summary>
        public override IEnumerable <Constraint> MarkTakens(bool[][] takens, int?[] grid, int?ix, int minValue, int maxValue)
        {
            if (ix == null)
            {
                return(null);
            }

            // “slot” is the value we just placed (index into AffectedCells, 0–2)
            var slot = Array.IndexOf(AffectedCells, ix.Value);

            if (slot == -1)
            {
                return(null);
            }

            // “unknown” is the value that is yet to be placed (index into AffectedCells, 0–2)
            var unknown = AffectedCells.IndexOf(af => grid[af] == null);

            if (unknown == -1)
            {
                return(null);
            }

            // Make sure that there is a second already-placed value
            if (grid[AffectedCells[3 - slot - unknown]] == null)
            {
                return(null);
            }

            for (var v = 0; v < takens[AffectedCells[unknown]].Length; v++)
            {
                if (!IsValid(
                        (grid[AffectedCells[0]] ?? v) + minValue,
                        (grid[AffectedCells[1]] ?? v) + minValue,
                        (grid[AffectedCells[2]] ?? v) + minValue
                        ))
                {
                    takens[AffectedCells[unknown]][v] = true;
                }
            }
            return(null);
        }
        /// <summary>Override; see base.</summary>
        public override ConstraintResult Process(SolverState state)
        {
            if (state.LastPlacedCell != null && !AffectedCells.Contains(state.LastPlacedCell.Value))
            {
                return(null);
            }

            var productAlready  = 1;
            var cellsLeftToFill = 0;

            foreach (var cell in AffectedCells)
            {
                if (state[cell] is int value)
                {
                    productAlready *= value;
                }
                else
                {
                    cellsLeftToFill++;
                }
            }
            if (cellsLeftToFill == 0 || (productAlready == 0 && Product == 0))
            {
                return(null);
            }

            var alreadyBroken = productAlready == 0 || (Product % productAlready != 0);

            foreach (var cell in AffectedCells)
            {
                state.MarkImpossible(cell, value =>
                                     alreadyBroken ||
                                     // The last remaining cell must have the exact required value
                                     (cellsLeftToFill == 1 && productAlready * value != Product) ||
                                     // The remaining cells must be factors of whatever is left to multiply
                                     (cellsLeftToFill > 1 && value == 0 ? (Product != 0) : ((Product / productAlready) % value != 0)));
            }
            return(null);
        }
Beispiel #11
0
            public override ConstraintResult Process(SolverState state)
            {
                if (state.LastPlacedCell == null)
                {
                    // The focus cell cannot be so large that it points outside the grid,
                    // nor can it have a value that points at a cell that already contains something other than a 9
                    state.MarkImpossible(AffectedCells[0], v => v > AffectedCells.Length - 1 || state.IsImpossible(AffectedCells[v], 9));
                }
                else if (state.LastPlacedCell.Value == AffectedCells[0])
                {
                    // The focus cell has been set, therefore place the 9 in the correct position
                    state.MustBe(AffectedCells[state.LastPlacedValue], 9);
                    for (var i = 1; i < AffectedCells.Length; i++)
                    {
                        if (i != state.LastPlacedValue)
                        {
                            state.MarkImpossible(AffectedCells[i], 9);
                        }
                    }
                }
                else if (AffectedCells.Contains(state.LastPlacedCell.Value))
                {
                    var index = AffectedCells.IndexOf(state.LastPlacedCell.Value);
                    if (state.LastPlacedValue == 9)
                    {
                        // A 9 has been placed somewhere, therefore set the focus cell to the correct value
                        // (This is the main difference with FindTheValueConstraint; it’s an optimization that assumes uniqueness)
                        state.MustBe(AffectedCells[0], index);
                    }
                    else
                    {
                        // A value other than 9 has been placed somewhere, therefore the focus cell cannot point at it anymore
                        state.MarkImpossible(AffectedCells[0], index);
                    }
                }

                return(null);
            }
        /// <summary>Override; see base.</summary>
        public override ConstraintResult Process(SolverState state)
        {
            // This will determine which values are still possible in which of the affected cells.
            var poss = Ut.NewArray(AffectedCells.Length, i => new bool[state.MaxValue - state.MinValue + 1]);

            // If any combination can be ruled out, this will contain the remaining combinations still available.
            List <int?[]> newComb = null;

            for (var i = 0; i < Combinations.Length; i++)
            {
                // Can this combination be ruled out?
                if (AffectedCells.Any((cellIx, lstIx) => Combinations[i][lstIx] != null && (state[cellIx] == null ? state.IsImpossible(cellIx, Combinations[i][lstIx].Value) : (state[cellIx].Value != Combinations[i][lstIx].Value))))
                {
                    if (newComb == null)
                    {
                        newComb = new List <int?[]>(Combinations.Take(i));
                    }
                }
                else
                {
                    if (newComb != null)
                    {
                        newComb.Add(Combinations[i]);
                    }

                    // Remember the possibilities for each cell
                    for (var lstIx = 0; lstIx < Combinations[i].Length; lstIx++)
                    {
                        if (Combinations[i][lstIx] == null)
                        {
                            poss[lstIx] = null;
                        }
                        else if (poss[lstIx] != null)
                        {
                            poss[lstIx][Combinations[i][lstIx].Value - state.MinValue] = true;
                        }
                    }
                }
            }

            // Mark any cell values that are no longer possible as taken
            for (var lstIx = 0; lstIx < poss.Length; lstIx++)
            {
                if (state[AffectedCells[lstIx]] == null && poss[lstIx] != null)
                {
                    for (var v = 0; v < poss[lstIx].Length; v++)
                    {
                        if (!poss[lstIx][v] && !state.IsImpossible(AffectedCells[lstIx], v + state.MinValue))
                        {
                            state.MarkImpossible(AffectedCells[lstIx], v + state.MinValue);
                        }
                    }
                }
            }

            if (newComb != null)
            {
                return new[] { new CombinationsConstraint(AffectedCells, newComb.ToArray()) }
            }
            ;
            return(null);
        }
Beispiel #13
0
        /// <summary>Override; see base.</summary>
        public override ConstraintResult Process(SolverState state)
        {
            if (state.LastPlacedCell is int cell)
            {
                var innerCell           = AffectedCells == null ? cell : AffectedCells.IndexOf(cell);
                var x                   = innerCell % SideLength;
                var y                   = innerCell / SideLength;
                var numUnknownsInColumn = Enumerable.Range(0, SideLength).Count(row => state[coord(x, row)] == null);
                if (numUnknownsInColumn < 2)
                {
                    // We just placed the last or second-last value in this column.
                    // If it’s the last, we need to make sure that no almost-complete column is about to be filled with the same parities.
                    // If it’s the second-last, we need to make sure that THIS column isn’t going to be filled with the same parities as another equal column.
                    for (var col = 0; col < SideLength; col++)
                    {
                        if (col == x)
                        {
                            continue;
                        }

                        var discrepantRow = -1;
                        for (var row = 0; row < SideLength; row++)
                        {
                            if (state[coord(numUnknownsInColumn == 0 ? col : x, row)] == null && state[coord(numUnknownsInColumn == 0 ? x : col, row)] != null)
                            {
                                if (discrepantRow == -1)
                                {
                                    discrepantRow = row;
                                }
                                else
                                {
                                    goto nextColumn;
                                }
                            }
                            else if (state[coord(col, row)] == null || state[coord(col, row)].Value % 2 != state[coord(x, row)].Value % 2)
                            {
                                goto nextColumn;
                            }
                        }
                        for (var v = state.MinValue; v <= state.MaxValue; v++)
                        {
                            if (v % 2 == state[coord(numUnknownsInColumn == 0 ? x : col, discrepantRow)].Value % 2)
                            {
                                state.MarkImpossible(coord(numUnknownsInColumn == 0 ? col : x, discrepantRow), v);
                            }
                        }
                        nextColumn :;
                    }
                }

                var numUnknownsInRow = Enumerable.Range(0, SideLength).Count(col => state[coord(col, y)] == null);
                if (numUnknownsInRow < 2)
                {
                    // See comment above for columns
                    for (var row = 0; row < SideLength; row++)
                    {
                        if (row == y)
                        {
                            continue;
                        }

                        var discrepantCol = -1;
                        for (var col = 0; col < SideLength; col++)
                        {
                            if (state[coord(col, numUnknownsInRow == 0 ? row : y)] == null && state[coord(col, numUnknownsInRow == 0 ? y : row)] != null)
                            {
                                if (discrepantCol == -1)
                                {
                                    discrepantCol = col;
                                }
                                else
                                {
                                    goto nextRow;
                                }
                            }
                            else if (state[coord(col, row)] == null || state[coord(col, row)].Value % 2 != state[coord(col, y)].Value % 2)
                            {
                                goto nextRow;
                            }
                        }
                        for (var v = state.MinValue; v <= state.MaxValue; v++)
                        {
                            if (v % 2 == state[coord(discrepantCol, numUnknownsInRow == 0 ? y : row)].Value % 2)
                            {
                                state.MarkImpossible(coord(discrepantCol, numUnknownsInRow == 0 ? row : y), v);
                            }
                        }
                        nextRow :;
                    }
                }
            }
            return(null);
        }