コード例 #1
0
ファイル: RuleBuilder.cs プロジェクト: david-pfx/Puzzlang
        // expand an ambiguous direction throughout a rule
        // error if more than one in pattern
        IList <AtomicRule> ExpandDirectionMulti(AtomicRule oldrule, Direction olddir)
        {
            var pcells = oldrule.Patterns.SelectMany(p => p.Cells
                                                     .SelectMany(c => c.Where(a => a.Direction == olddir)));

            if (pcells.Count() != 1)
            {
                _parser.CompileError("'{0}' in action cannot be matched", olddir);
            }

            // expand one rule per single direction
            var newrules = new List <AtomicRule>();

            foreach (var newdir in _expanddirlookup[olddir])
            {
                var newrule = oldrule.Clone();
                for (var riter = new RuleIterator {
                    Rule = oldrule
                }; !riter.Done; riter.Step())
                {
                    newrule.Patterns[riter.SubRuleIndex].Cells[riter.CellIndex] = ReplaceDirection(riter.PatternAtoms, olddir, newdir);
                    newrule.Actions[riter.SubRuleIndex].Cells[riter.CellIndex]  = ReplaceDirection(riter.ActionAtoms, olddir, newdir);
                }
                newrules.AddRange(ExpandRule(newrule));
            }
            return(newrules);
        }
コード例 #2
0
ファイル: RuleBuilder.cs プロジェクト: david-pfx/Puzzlang
        //==========================================================================
        //
        // compile a rule
        internal CompiledRule CompileRule(AtomicRule rule)
        {
            _parser.DebugLog("{0}", rule);
            if (rule.Directions.Count != 1)
            {
                throw Error.Assert("direction count");
            }
            for (int i = 0; i < rule.Patterns.Count; i++)
            {
                // TODO: check singleton rules here
            }
            var crule = new CompiledRule {
                RuleId        = rule.RuleId,
                RuleDirection = rule.Directions.First(),
                PatternCode   = CompilePattern(rule.Directions.First(), rule.Patterns),
                ActionCode    = (rule.HasAction)
          ? CompileActions(rule.Directions.First(), rule.Patterns, rule.Actions)
          : RuleCode.Empty,
                CommandCode = (rule.HasCommand)
          ? CompileCommand(rule.Commands)
          : RuleCode.Empty,
            };

            return(crule);
        }
コード例 #3
0
ファイル: RuleBuilder.cs プロジェクト: david-pfx/Puzzlang
        // expand an OR symbol throughout a rule
        // error if more than one in pattern
        IList <AtomicRule> ExpandSymbolMulti(AtomicRule oldrule, ObjectSymbol oldsym)
        {
            var pcells = oldrule.Patterns.SelectMany(p => p.Cells
                                                     .SelectMany(c => c.Where(a => a.Symbol == oldsym && !a.IsNegated)));

            if (pcells.Count() != 1)
            {
                return(null);
            }

            // expand one rule per object id
            var newrules = new List <AtomicRule>();

            foreach (var newobj in oldsym.ObjectIds)
            {
                var newrule = oldrule.Clone();
                for (var riter = new RuleIterator {
                    Rule = oldrule
                }; !riter.Done; riter.Step())
                {
                    newrule.Patterns[riter.SubRuleIndex].Cells[riter.CellIndex] = ReplaceObject(riter.PatternAtoms, oldsym, newobj);
                    newrule.Actions[riter.SubRuleIndex].Cells[riter.CellIndex]  = ReplaceObject(riter.ActionAtoms, oldsym, newobj);
                }
                newrules.AddRange(ExpandRule(newrule));
            }
            return(newrules);
        }
コード例 #4
0
ファイル: RuleBuilder.cs プロジェクト: david-pfx/Puzzlang
        // Convert every relative direction into absolute
        AtomicRule MakeAbsolute(AtomicRule rule, Direction ruledir)
        {
            var newrule = rule.Clone();

            newrule.Directions = new HashSet <Direction>()
            {
                ruledir
            };
            MakeAbsolute(newrule.Patterns, ruledir);
            if (newrule.HasAction)
            {
                MakeAbsolute(newrule.Actions, ruledir);
            }
            return(newrule);
        }
コード例 #5
0
ファイル: RuleBuilder.cs プロジェクト: david-pfx/Puzzlang
 // expand ambiguous directions in rule pattern known to have no matching action
 // replacing by individuals (absolute or relative)
 // abs could be fixed by more powerful vm code
 IList <AtomicRule> ExpandDirectionSimple(AtomicRule oldrule)
 {
     for (var riter = new RuleIterator {
         Rule = oldrule
     }; !riter.Done; riter.Step())
     {
         // look for any ambiguous unmatched pattern directions, just one each time
         var patom = riter.PatternAtoms.FirstOrDefault(a => _expanddirlookup.ContainsKey(a.Direction));
         if (patom != null)
         {
             return(ExpandDirectionSingle(riter, patom.Direction));
         }
     }
     return(new List <AtomicRule> {
         oldrule
     });
 }
コード例 #6
0
ファイル: RuleBuilder.cs プロジェクト: david-pfx/Puzzlang
        // expand a rule where an occurrence on an action does not match its pattern
        // replacing combination directions and symbols by individuals (absolute or relative)
        // could be fixed by more powerful vm code
        IList <AtomicRule> ExpandRule(AtomicRule oldrule)
        {
            if (!oldrule.HasAction)
            {
                return(ExpandDirectionSimple(oldrule));
            }

            // check each cell of each subrule
            for (var riter = new RuleIterator {
                Rule = oldrule
            }; !riter.Done; riter.Step())
            {
                // Do no expansion on random actions
                if (riter.ActionAtoms.Any(a => a.IsRandom))
                {
                    oldrule.Prefixes.Add(RulePrefix.Final);
                }
                else
                {
                    // check for action atom with ambiguous direction and no matching pattern atom
                    var datom = riter.ActionAtoms.FirstOrDefault(a => _expanddirlookup.ContainsKey(a.Direction) &&
                                                                 !riter.PatternAtoms.Any(p => p.Matches(a) && p.Direction == a.Direction));
                    if (datom != null)
                    {
                        return(ExpandDirectionMulti(oldrule, datom.Direction));
                    }

                    // check for action atom with property symbol and no matching pattern atom
                    var satom = riter.ActionAtoms.FirstOrDefault(a => a.Symbol.Kind == SymbolKind.Property &&
                                                                 !a.IsNegated && !a.IsRandom && !riter.PatternAtoms.Any(p => p.Matches(a)));
                    if (satom != null)
                    {
                        var newrules = ExpandSymbolMulti(oldrule, satom.Symbol) ?? ExpandPropertyMatcher(riter);
                        if (newrules == null)
                        {
                            _parser.CompileError("'{0}' in action cannot be matched", satom.Symbol.Name);
                        }
                        else
                        {
                            return(newrules);
                        }
                    }
                }
            }
            return(ExpandDirectionSimple(oldrule));
        }
コード例 #7
0
ファイル: RuleBuilder.cs プロジェクト: david-pfx/Puzzlang
        // Expand until rules are atomic, make absolute, return list of atomic rules
        internal IList <AtomicRule> BuildRuleList(AtomicRule arule, int groupno)
        {
            Logger.WriteLine(2, "Build group {0} rule {1}", groupno, arule.RuleId);

            // how many directions do we need?
            var singles = arule.Patterns.All(p => p.Cells.Count == 1) &&
                          arule.Patterns.All(p => p.Cells[0].All(a => _ruledirlookup.ContainsKey(a.Direction)));
            var ruledirs = (arule.Directions.Count == 0)
        ? _ruledirlookup[singles ? Direction.None : Direction.Orthogonal]
        : arule.Directions.SelectMany(d => _ruledirlookup[d]).Distinct();

            // expand ambiguous directions and symbols into absolute/relative
            var exrules = ExpandRule(arule);

            // convert relative directions into absolute clones
            var absrules = ruledirs
                           .SelectMany(d => exrules
                                       .Select(r => MakeAbsolute(r, d))).ToList();

            return(absrules);
        }
コード例 #8
0
ファイル: ParseManager.cs プロジェクト: david-pfx/Puzzlang
        // expand rule and add compiled rule to game data
        internal void AddRule(int ruleid, IList <RulePrefix> prefixes, IList <Direction> directions,
                              IList <SubRule> pattern, IList <SubRule> action, IList <CommandCall> commands)
        {
            // create the base rule with unexpanded directions
            var arule = new AtomicRule {
                RuleId     = ruleid,
                Prefixes   = new HashSet <RulePrefix>(prefixes),
                Directions = new HashSet <Direction>(directions),
                Patterns   = pattern,
                Actions    = action,
                Commands   = commands,
            };

            // expand rules, all going in the same group, then compile them
            var rulegroup = _gamedef.GetRuleGroup(arule.Prefixes, _inloop ? _loopcounter : 0);

            foreach (var prule in _rulebuilder.BuildRuleList(arule, rulegroup.Id))
            {
                _atomicrules.Add(prule);
                rulegroup.Rules.Add(_rulebuilder.CompileRule(prule));
                rulegroup.IsFinal |= prule.IsFinal; // propagate retry suppression to group
            }
        }