/** * Returns a FieldIndex which Keeps a count on how many times a particular field is used with an * equality check in the sinks. */ private FieldIndex registerFieldIndex( final int index, final InternalReadAccessor fieldExtractor) { FieldIndex fieldIndex = null; // is linkedlist null, if so create and add if (this.hashedFieldIndexes == null) { this.hashedFieldIndexes = new LinkedList<FieldIndex>(); fieldIndex = new FieldIndex(index, fieldExtractor); this.hashedFieldIndexes.add(fieldIndex); } // still null, so see if it already exists if (fieldIndex == null) { fieldIndex = findFieldIndex(index); } // doesn't exist so create it if (fieldIndex == null) { fieldIndex = new FieldIndex(index, fieldExtractor); this.hashedFieldIndexes.add(fieldIndex); } fieldIndex.increaseCounter(); return fieldIndex; }
private FieldIndex findFieldIndex(final int index) { for (FieldIndex node = this.hashedFieldIndexes.getFirst(); node != null; node = node.getNext()) { if (node.getIndex() == index) { return node; } } return null; }
public void byPassModifyToBetaNode( final InternalFactHandle factHandle, final ModifyPreviousTuples modifyPreviousTuples, final PropagationContext context, final InternalWorkingMemory workingMemory) { final Object object = factHandle.getObject(); // We need to iterate in the same order as the assert if (this.hashedFieldIndexes != null) { // Iterate the FieldIndexes to see if any are hashed for (FieldIndex fieldIndex = this.hashedFieldIndexes.getFirst(); fieldIndex != null; fieldIndex = fieldIndex.getNext()) { if (!fieldIndex.isHashed()) { continue; } // this field is hashed so set the existing hashKey and see if there is a sink for it final AlphaNode sink = (AlphaNode) this.hashedSinkMap.get(new HashKey(fieldIndex, object)); if (sink != null) { // only alpha nodes are hashable sink.getObjectSinkPropagator() .byPassModifyToBetaNode(factHandle, modifyPreviousTuples, context, workingMemory); } } } // propagate unhashed if (this.hashableSinks != null) { for (ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { // only alpha nodes are hashable ((AlphaNode) sink) .getObjectSinkPropagator() .byPassModifyToBetaNode(factHandle, modifyPreviousTuples, context, workingMemory); } } if (this.otherSinks != null) { // propagate others for (ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { // compound alpha, lianode or betanode sink.byPassModifyToBetaNode(factHandle, modifyPreviousTuples, context, workingMemory); } } }
private static ArrayList<SkillType> FindTowersInCluster(boolean[][] cluster, Player player) { // checks if there is a piece in front of the given piece, // if there is, there might be a tower; calling specific find-tower functions // does this for all 8 directions. ArrayList<Towers> towerList = new ArrayList<Towers>(); for (int nx = 0; nx < Gameboard.COLUMNS_AND_ROWS; nx++) { // checking for all elements in the cluster... for (int ny = 0; ny < Gameboard.COLUMNS_AND_ROWS; ny++) { if (cluster[nx][ny]) { for (int i = 0; i < 8; i++) { // ...in all directions FieldIndex f = new FieldIndex(nx, ny); FieldIndex start = f.Up(i); if (start.Valid() && cluster[start.x()][start.y()]) { towerList.addAll(FindShootTower(i, start, cluster)); towerList.addAll(FindBuildTower(i, start, cluster)); if (i < 4) { towerList.addAll(FindSilenceTower(i, start, cluster)); towerList.addAll(FindFiveTower(i, start, cluster)); } if (i < 2) { towerList.addAll(FindMultipleSkillsTower(i, start, cluster)); } } } } } } ArrayList<SkillType> skillList = new ArrayList<SkillType>(); // marking the positions of the towers as built: // Gdx.app.log("Tower", "found "+Integer.toString(towerList.size())+" towers:"); for (Towers t : towerList) { // Gdx.app.log("", t.toString()); if (!player.isSilenced()) { for (FieldIndex f : t.tower) { if (!f.Valid()) { Gdx.app.error("Tower", "Invalid Tower: " + t.toString()); } Game.getInstance().getGameboard().setMarkToBuilt(f.x(), f.y(), player); } } skillList.add(t.towerType); } return skillList; }
private FieldIndex unregisterFieldIndex(final int index) { final FieldIndex fieldIndex = findFieldIndex(index); fieldIndex.decreaseCounter(); // if the fieldcount is 0 then remove it from the linkedlist if (fieldIndex.getCount() == 0) { this.hashedFieldIndexes.remove(fieldIndex); // if the linkedlist is empty then null it if (this.hashedFieldIndexes.isEmpty()) { this.hashedFieldIndexes = null; } } return fieldIndex; }
public ObjectSink[] getSinks() { if (this.sinks != null) { return sinks; } ObjectSink[] sinks = new ObjectSink[size()]; int at = 0; if (this.hashedFieldIndexes != null) { // Iterate the FieldIndexes to see if any are hashed for (FieldIndex fieldIndex = this.hashedFieldIndexes.getFirst(); fieldIndex != null; fieldIndex = fieldIndex.getNext()) { if (!fieldIndex.isHashed()) { continue; } // this field is hashed so set the existing hashKey and see if there is a sink for it final int index = fieldIndex.getIndex(); final Iterator it = this.hashedSinkMap.newIterator(); for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next()) { HashKey hashKey = (HashKey) entry.getKey(); if (hashKey.getIndex() == index) { sinks[at++] = (ObjectSink) entry.getValue(); } } } } if (this.hashableSinks != null) { for (ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { sinks[at++] = sink; } } if (this.otherSinks != null) { for (ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { sinks[at++] = sink; } } this.sinks = sinks; return sinks; }
public void propagateModifyObject( final InternalFactHandle factHandle, final ModifyPreviousTuples modifyPreviousTuples, final PropagationContext context, final InternalWorkingMemory workingMemory) { final Object object = factHandle.getObject(); // Iterates the FieldIndex collection, which tells you if particularly field is hashed or not // if the field is hashed then it builds the hashkey to return the correct sink for the current // objects slot's // value, one object may have multiple fields indexed. if (this.hashedFieldIndexes != null) { // Iterate the FieldIndexes to see if any are hashed for (FieldIndex fieldIndex = this.hashedFieldIndexes.getFirst(); fieldIndex != null; fieldIndex = fieldIndex.getNext()) { if (!fieldIndex.isHashed()) { continue; } // this field is hashed so set the existing hashKey and see if there is a sink for it final AlphaNode sink = (AlphaNode) this.hashedSinkMap.get(new HashKey(fieldIndex, object)); if (sink != null) { // go straight to the AlphaNode's propagator, as we know it's true and no need to retest sink.getObjectSinkPropagator() .propagateModifyObject(factHandle, modifyPreviousTuples, context, workingMemory); } } } // propagate unhashed if (this.hashableSinks != null) { for (ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { doPropagateModifyObject(factHandle, modifyPreviousTuples, context, workingMemory, sink); } } if (this.otherSinks != null) { // propagate others for (ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { doPropagateModifyObject(factHandle, modifyPreviousTuples, context, workingMemory, sink); } } }
public ObjectSinkPropagator removeObjectSink(final ObjectSink sink) { this.sinks = null; // dirty it, so it'll rebuild on next get if (sink.getType() == NodeTypeEnums.AlphaNode) { final AlphaNode alphaNode = (AlphaNode) sink; final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint(); if (fieldConstraint instanceof IndexableConstraint) { final IndexableConstraint indexableConstraint = (IndexableConstraint) fieldConstraint; final FieldValue value = indexableConstraint.getField(); if (isHashable(indexableConstraint)) { final InternalReadAccessor fieldAccessor = indexableConstraint.getFieldExtractor(); final int index = fieldAccessor.getIndex(); final FieldIndex fieldIndex = unregisterFieldIndex(index); if (fieldIndex.isHashed()) { HashKey hashKey = new HashKey(index, value, fieldAccessor); this.hashedSinkMap.remove(hashKey); if (fieldIndex.getCount() <= this.alphaNodeHashingThreshold - 1) { // we have less than three so unhash unHashSinks(fieldIndex); } } else { this.hashableSinks.remove(alphaNode); } if (this.hashableSinks != null && this.hashableSinks.isEmpty()) { this.hashableSinks = null; } return size() == 1 ? new SingleObjectSinkAdapter(getSinks()[0]) : this; } } } this.otherSinks.remove((ObjectSinkNode) sink); if (this.otherSinks.isEmpty()) { this.otherSinks = null; } return size() == 1 ? new SingleObjectSinkAdapter(getSinks()[0]) : this; }
private static boolean[][] FindClusterRecurse(FieldIndex ind, boolean[][] taken, Mark type) { // recursive function that finds a cluster Gameboard board = Game.getInstance().getGameboard(); taken[(int) ind.x()][(int) ind.y()] = true; for (FieldIndex i : ind.GetNeigbours()) { if (board.getMark(i.x(), i.y()) == type && taken[i.x()][i.y()] == false) { taken = FindClusterRecurse(i, taken, type); } } return taken; }
private static ArrayList<Towers> FindMultipleSkillsTower( int direction, FieldIndex startPoint, boolean[][] cluster) { // checks for the two last pieces of a multiple-skills tower in the given direction // startPoint should be the second index // returns number of found towers ArrayList<Towers> towerList = new ArrayList<Towers>(); FieldIndex right = startPoint.Right(direction); if (right.Valid() && cluster[right.x()][right.y()]) { FieldIndex down = right.Down(direction); if (down.Valid() && cluster[down.x()][down.y()]) { Towers tower = new Towers(startPoint, direction); // initing the tower tower.add(right); tower.add(down); tower.towerType = SkillType.SKILLCAP; towerList.add(tower); } } return towerList; }
public ObjectSinkPropagator addObjectSink(ObjectSink sink, int alphaNodeHashingThreshold) { this.sinks = null; // dirty it, so it'll rebuild on next get if (sink.getType() == NodeTypeEnums.AlphaNode) { final AlphaNode alphaNode = (AlphaNode) sink; final InternalReadAccessor readAccessor = getHashableAccessor(alphaNode); if (readAccessor != null) { final int index = readAccessor.getIndex(); final FieldIndex fieldIndex = registerFieldIndex(index, readAccessor); // DROOLS-678 : prevent null values from being hashed as 0s final FieldValue value = ((IndexableConstraint) alphaNode.getConstraint()).getField(); if (fieldIndex.getCount() >= this.alphaNodeHashingThreshold && this.alphaNodeHashingThreshold != 0 && !value.isNull()) { if (!fieldIndex.isHashed()) { hashSinks(fieldIndex); } // no need to check, we know the sink does not exist this.hashedSinkMap.put( new HashKey(index, value, fieldIndex.getFieldExtractor()), alphaNode, false); } else { if (this.hashableSinks == null) { this.hashableSinks = new ObjectSinkNodeList(); } this.hashableSinks.add(alphaNode); } return this; } } if (this.otherSinks == null) { this.otherSinks = new ObjectSinkNodeList(); } this.otherSinks.add((ObjectSinkNode) sink); return this; }
private static ArrayList<Towers> FindShootTower( int direction, FieldIndex startPoint, boolean[][] cluster) { // checks for the two last pieces of a shoot tower in the given direction // startpoint should be the second index // returns number of found towers FieldIndex right = startPoint.Right(direction); FieldIndex left = startPoint.Left(direction); boolean leftPart = left.Valid() && cluster[left.x()][left.y()]; boolean rightPart = right.Valid() && cluster[right.x()][right.y()]; ArrayList<Towers> towerList = new ArrayList<Towers>(); if (leftPart && rightPart) { Towers tow = new Towers(startPoint, direction); tow.add(left); tow.add(right); tow.towerType = SkillType.SHOOT; towerList.add(tow); } return towerList; }
void unHashSinks(final FieldIndex fieldIndex) { final int index = fieldIndex.getIndex(); // this is the list of sinks that need to be removed from the hashedSinkMap final List<HashKey> unhashedSinks = new ArrayList<HashKey>(); final Iterator iter = this.hashedSinkMap.newIterator(); ObjectHashMap.ObjectEntry entry = (ObjectHashMap.ObjectEntry) iter.next(); while (entry != null) { final AlphaNode alphaNode = (AlphaNode) entry.getValue(); final IndexableConstraint indexableConstraint = (IndexableConstraint) alphaNode.getConstraint(); // only alpha nodes that have an Operator.EQUAL are in sinks, so only check if it is // the right field index if (index == indexableConstraint.getFieldExtractor().getIndex()) { final FieldValue value = indexableConstraint.getField(); if (this.hashableSinks == null) { this.hashableSinks = new ObjectSinkNodeList(); } this.hashableSinks.add(alphaNode); unhashedSinks.add(new HashKey(index, value, fieldIndex.getFieldExtractor())); } entry = (ObjectHashMap.ObjectEntry) iter.next(); } for (HashKey hashKey : unhashedSinks) { this.hashedSinkMap.remove(hashKey); } if (this.hashedSinkMap.isEmpty()) { this.hashedSinkMap = null; } fieldIndex.setHashed(false); }
void hashSinks(final FieldIndex fieldIndex) { if (this.hashedSinkMap == null) { this.hashedSinkMap = new ObjectHashMap(); } final int index = fieldIndex.getIndex(); final InternalReadAccessor fieldReader = fieldIndex.getFieldExtractor(); ObjectSinkNode currentSink = this.hashableSinks.getFirst(); while (currentSink != null) { final AlphaNode alphaNode = (AlphaNode) currentSink; final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint(); final IndexableConstraint indexableConstraint = (IndexableConstraint) fieldConstraint; // position to the next sink now because alphaNode may be removed if the index is equal. If we // were to do this // afterwards, currentSink.nextNode would be null currentSink = currentSink.getNextObjectSinkNode(); // only alpha nodes that have an Operator.EQUAL are in hashableSinks, so only check if it is // the right field index if (index == indexableConstraint.getFieldExtractor().getIndex()) { final FieldValue value = indexableConstraint.getField(); this.hashedSinkMap.put(new HashKey(index, value, fieldReader), alphaNode); // remove the alpha from the possible candidates of hashable sinks since it is now hashed hashableSinks.remove(alphaNode); } } if (this.hashableSinks.isEmpty()) { this.hashableSinks = null; } fieldIndex.setHashed(true); }
private Towers(FieldIndex f, int direction) { tower = new ArrayList<FieldIndex>(4); tower.add(f.Down(direction)); tower.add(f); }
private static ArrayList<Towers> FindFiveTower( int direction, FieldIndex startPoint, boolean[][] cluster) { // checks for the three last pieces of a five-in-a-row tower in the given direction // startPoint should be the second index // returns a list of found towers ArrayList<Towers> towerList = new ArrayList<Towers>(); Towers tower = new Towers(startPoint, direction); FieldIndex up = startPoint.Up(direction); if (up.Valid() && cluster[up.x()][up.y()]) { tower.add(up); up = up.Up(direction); if (up.Valid() && cluster[up.x()][up.y()]) { tower.add(up); up = up.Up(direction); if (up.Valid() && cluster[up.x()][up.y()]) { tower.add(up); towerList.add(tower); Game.getInstance().setShowVictoryScreen(true); return towerList; } } } return towerList; // returning the empty tower list }
private static ArrayList<Towers> FindSilenceTower( int direction, FieldIndex startPoint, boolean[][] cluster) { // checks for the two last pieces of a silence tower in the given direction // startPoint should be the second index // returns number of found towers ArrayList<Towers> towerList = new ArrayList<Towers>(); FieldIndex right = startPoint.Right(direction); FieldIndex left = startPoint.Left(direction); boolean leftPart = left.Valid() && cluster[left.x()][left.y()]; boolean rightPart = right.Valid() && cluster[right.x()][right.y()]; if (leftPart) { FieldIndex up = left.Up(direction); if (up.Valid() && cluster[up.x()][up.y()]) { Towers leftTower = new Towers(startPoint, direction); // initing the tower leftTower.add(left); leftTower.add(up); leftTower.towerType = SkillType.SILENCE; towerList.add(leftTower); } } if (rightPart) { FieldIndex up = right.Up(direction); if (up.Valid() && cluster[up.x()][up.y()]) { Towers rightTower = new Towers(startPoint, direction); // initing the tower rightTower.add(right); rightTower.add(up); rightTower.towerType = SkillType.SILENCE; towerList.add(rightTower); } } return towerList; }
public HashKey(FieldIndex fieldIndex, Object value) { this.setValue(fieldIndex.getIndex(), value, fieldIndex.getFieldExtractor()); }