svoid nlLogic_battleItOut(L battleSpace, LS facts) { new Matches mm; new MultiMap trumps; // get conflict clusters new Clusters conflictClusters; new Set _ruleIDs; for (RuleWithParams r : battleSpace) { addIfNotNull(_ruleIDs, r.rule.globalID); for (S option : unnull(r.rule.options)) if (match_vbar("conflicts with *|trumps *", option, mm)) { S r1 = r.rule.globalID, r2 = mm.unq(0); treeSetClusters_add(conflictClusters, r1, r2); if (match("trumps *", option)) trumps.put(r1, r2); } } for (S s : facts) { bool trump = match("rule * trumps rule *", s, mm); if (trump || match("rule * conflicts with rule *", s, mm)) { S r1 = mm.unq(0), r2 = mm.unq(1); if (_ruleIDs.contains(r1) && _ruleIDs.contains(r2)) { treeSetClusters_add(conflictClusters, r1, r2); if (trump) trumps.put(r1, r2); } } } if (nempty(conflictClusters)) print("Have conflict clusters: " + sfu(conflictClusters)); // Detect winners final new HashSet toRemove; for (Collection ruleIDs : uniquifyList_identity(values(conflictClusters))) { ruleIDs = new LinkedHashSet(ruleIDs); for (S id : cloneList(ruleIDs)) { LS losers = trumps.get(id); removeAll(ruleIDs, losers); toRemove.addAll(losers); } S winner = random(ruleIDs); L removing = listWithout(ruleIDs, winner); print("Winner: " + winner + ", removing: " + removing); toRemove.addAll(removing); } // Remove losers if (nempty(toRemove)) { for (ListIterator i = listIterator(battleSpace); i.hasNext(); ) if (toRemove.contains(i.next().rule.globalID)) i.remove(); print("Rules narrowed down to: " + collect(collect(battleSpace, 'rule), 'globalID)); } }