protected void tryReaction( final SquirmCellSlot cell_grid[][], final SquirmCell cell, final Vector<SquirmCell> neighbours, char us_type, int us_state, boolean current_bond, char them_type, int them_state, int future_us_state, boolean future_bond, int future_them_state, final SquirmReaction reaction) { // us_type is one of {e,f,a,b,c,d,x} if (us_type != 'e' && us_type != 'f' && us_type != 'a' && us_type != 'b' && us_type != 'c' && us_type != 'd' && us_type != 'x') throw new Error("SquirmChemistry::Reaction() : invalid us_type"); // them_type is one of {e,f,a,b,c,d,x,y} if (them_type != 'e' && them_type != 'f' && them_type != 'a' && them_type != 'b' && them_type != 'c' && them_type != 'd' && them_type != 'x' && them_type != 'y') throw new Error("SquirmChemistry::Reaction() : invalid them_type"); // sanity check on the states requested if (us_state < 0 || them_state < 0 || future_us_state < 0 || future_them_state < 0) throw new Error("SquirmChemistry::tryReaction() : states less than zero not permitted"); // Are we the right kind of cell for this reaction? if ((us_type != 'x' && cell.isTypeAndState(us_type, us_state)) || (us_type == 'x' && cell.isState(us_state))) { // do we have a neighbour (bonded/not) that is the right kind for // this reaction? final Vector<SquirmCell> search_from = current_bond ? cell.getBonds() : neighbours; Vector<SquirmCell> ns; // if them_type specified then search for it if (them_type != 'x' && them_type != 'y') ns = getThoseOfTypeAndState(search_from, them_type, them_state); // if unspecified but to be same as us_type then search for it else if (them_type == 'x' && us_type == 'x') ns = getThoseOfTypeAndState(search_from, cell.getType(), them_state); // must be unspecified else if ((them_type == 'x' && us_type != 'x') || them_type == 'y') ns = getThoseOfState(search_from, them_state); else throw new Error("SquirmChemistry::tryReaction() : unexpected case statement"); // try the reaction on each of the possibles for (final Enumeration<SquirmCell> e = ns.elements(); e.hasMoreElements(); ) { final SquirmCell n = (SquirmCell) e.nextElement(); // reactions can happen if the two cells are right next to each // other (share a face) or over a diagonal (share a corner) if // the other diagonal // doesn't have a bond boolean can_react = false; if (rightNextToEachOther(cell, n)) can_react = true; else { // if either other diagonal square is empty then OK if (cell_grid[cell.getX()][n.getY()].queryEmpty() || cell_grid[n.getX()][cell.getY()].queryEmpty()) can_react = true; else { // otherwise, if there is no bond between diagonals then // still OK final SquirmCell cellA = cell_grid[cell.getX()][n.getY()].getOccupant(); final SquirmCell cellB = cell_grid[n.getX()][cell.getY()].getOccupant(); if (!cellA.getBonds().contains(cellB)) { can_react = true; } // End of if } } // End of if - else // if (can_react) { // make or break bonds as specified if (current_bond && !future_bond) { LOGGER.info( "Breaking bond : UsType=" + us_type + " UsState=" + us_state + " ThemType=" + them_type + " ThemState=" + them_state); cell.breakBondWith(n); } else if (!current_bond && future_bond) { LOGGER.info( "Making bond for reaction : UsType=" + us_type + " UsState=" + us_state + " ThemType=" + them_type + " ThemState=" + them_state + " reaction=" + reaction); cell.makeBondWith(n, reaction); } // set our states to their new values cell.setState(future_us_state); n.setState(future_them_state); break; } } } }
protected boolean rightNextToEachOther(SquirmCell cell1, SquirmCell cell2) { return (Math.abs(cell1.getX() - cell2.getX()) + Math.abs(cell1.getY() - cell2.getY()) < 2); }