package util.gdl.transforms; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import util.gdl.grammar.Gdl; import util.gdl.grammar.GdlConstant; import util.gdl.grammar.GdlDistinct; import util.gdl.grammar.GdlLiteral; import util.gdl.grammar.GdlPool; import util.gdl.grammar.GdlProposition; import util.gdl.grammar.GdlRule; import util.gdl.grammar.GdlSentence; import util.gdl.grammar.GdlTerm; import util.gdl.grammar.GdlVariable; import util.statemachine.Role; public class LegalSplitter { private static final GdlConstant LEGAL = GdlPool.getConstant("legal"); /** * Modifies the rules for legal moves in a GDL description so that * they use constants for each player in place of variables; e.g. * rules with the head (does ?player (move ?x ?y)) are replaced * with rules with heads (does white (move ?x ?y)), * (does black (move ?x ?y)), etc. This may be useful when trying * to identify which types of moves are mutually exclusive, i.e., * only one player can play such a move at a time. (See * MoveMutexFinder.) */ public static List<Gdl> run(List<Gdl> description) { List<Gdl> newDescription = new ArrayList<Gdl>(); List<Role> roles = Role.computeRoles(description); for(Gdl gdl : description) { if(gdl instanceof GdlRule) { GdlRule rule = (GdlRule) gdl; GdlSentence head = rule.getHead(); if(head.getName().equals(LEGAL)) { if(head instanceof GdlProposition || head.arity() != 2) throw new RuntimeException("Head of rule is improper 'legal' sentence: " + rule); //Is the player name given by a variable? GdlTerm playerTerm = head.get(0); if(playerTerm instanceof GdlVariable) { //Here we split the rule up for(Role role : roles) { GdlConstant playerName = role.getName().getName(); //Substitute into the rule... GdlRule newRule = CommonTransforms.replaceVariable(rule, (GdlVariable) playerTerm, playerName); newDescription.add(newRule); } } else { newDescription.add(rule); } } else { newDescription.add(rule); } } else { newDescription.add(gdl); } } removeImpossibleRules(newDescription); return newDescription; } //This won't get all the rules that can't possibly be true, //but it will get those that can't be true based on a //"distinct" literal between two constants. private static void removeImpossibleRules(List<Gdl> newDescription) { Iterator<Gdl> itr = newDescription.iterator(); while(itr.hasNext()) { Gdl gdl = itr.next(); if(gdl instanceof GdlRule) { GdlRule rule = (GdlRule) gdl; //Look for a bad GdlDistinct for(GdlLiteral literal : rule.getBody()) { if(literal instanceof GdlDistinct) { GdlDistinct distinct = (GdlDistinct) literal; //Is it (distinct c c) for some constant c? if(distinct.getArg1() instanceof GdlConstant && distinct.getArg1() == distinct.getArg2()) { itr.remove(); System.out.println("Removed impossible rule " + rule); break; //out of the rule } } } } } } }