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 }