Files

85 lines
1.8 KiB
Go

package logic
import (
"errors"
"fmt"
"git.kleiax.de/homepage/field"
"git.kleiax.de/homepage/logic/strategies"
)
var ErrNoProgress = errors.New("no strategy can solve the puzzle")
type Solver struct {
strategies []strategies.Strategy
field *field.Field
}
func (s *Solver) Add(strategy strategies.Strategy) {
if strategy != nil {
s.strategies = append(s.strategies, strategy)
}
}
func (s *Solver) InitStrategies(f *field.Field) error {
if f == nil || !f.IsValid() {
return field.ErrInvalidField
}
s.field = f
for _, strategy := range s.strategies {
strategy.Init(f)
}
return nil
}
// InitStragies is kept for compatibility. New code should use InitStrategies.
func (s *Solver) InitStragies(f *field.Field) error {
return s.InitStrategies(f)
}
// Run applies strategies from the requested index until the field is solved or
// no strategy can make progress. It returns false without an error for a valid
// but currently unsolved field.
func (s *Solver) Run(start int) (bool, error) {
if s.field == nil || !s.field.IsValid() {
return false, field.ErrInvalidField
}
if start < 0 || start > len(s.strategies) {
return false, fmt.Errorf("strategy index %d out of range", start)
}
for {
if s.field.IsSolved() {
return true, nil
}
progress := false
for index := start; index < len(s.strategies); index++ {
strategy := s.strategies[index]
if strategy.SearchProgressableCells() == 0 {
continue
}
changes, err := strategy.ApplyAll()
if err != nil {
return false, fmt.Errorf("apply strategy %q: %w", strategy.Name(), err)
}
if len(changes) == 0 {
continue
}
progress = true
break
}
if !progress {
return false, nil
}
start = 0
}
}
func (s *Solver) Search() {}
func (s *Solver) GetSolutionPath() []field.ExternalChange {
return nil
}