anchor.diff:            return playedHasExit == neighborHasExit;
           }
         });
  -    
  +
     }
   
     bool playSabotage(BoardLoc loc){
       if(isLegalSabotage(loc)){
         boardMap.remove(loc);
         fringe.add(loc);
  +      //TODO remove fringe locations that are now unreachable
         return true;
       } else {
         return false;
  
positive.code:           return true;
          } else {
            var playedHasExit = CardUtil.exits(card.type, playedDir).contains(dir);
            var neighborHasExit = CardUtil.exits(boardMap[neighborLoc].card.type, 
              boardMap[neighborLoc].dir).contains(CardUtil.opposite(dir));
            
            //return true if both have the exit, or neither have it
            log("Played type: ${card.type} Played dir: ${playedDir}" +
              "Neighbor type: ${boardMap[neighborLoc].card.type} Neighbor dir: ${boardMap[neighborLoc].dir}");
  
negative.code:     if(!fringe.contains(loc)) return false;
  
      //Test each side of the played card to see if it fits
      return CardUtil.allDirections.every(
        (CardDirection dir) {
          BoardLoc neighborLoc = loc.neighborLoc(dir);
          if (!boardMap.keys.contains(neighborLoc)) {
  