I think that counting rights can make sense here.
The idea is to count how many directions your collective objects can move. This is equivalent to the number of open squares or enemy units (available squares) located next to your moving objects. If an available square is affected by more than one of your parts, it is counted several times. We will call each available square / potential direction free.
You start by counting the number of initial freedoms. You only need to count the number of moving parts in the front row without touching the water. No other part can move, and each part has only one direction in which they can move.
After that, the algorithm for updating the number of freedoms is quite simple. You count the number of freedoms that the old position has, subtracting the number of your blocks that it blocks, and count the number of freedoms that the new position has, again subtracting the number of blocks it blocks. You add this to general freedoms, and you have a new meaning.
I haven't coded java for a while, so my examples will be in pseudo-code / python, but the idea should be passed.
directions = [(0,1),(0,-1),(1,0),(-1,0)] for d in directions: if (SpaceIsAvailable(oldPosition + d)): liberties-- if (SpaceIsMovable(oldPosition + d)): liberties++ if(SpaceIsAvailable(newPosition + d)): liberties++ if(SpaceIsMovable(newPosition + d)): liberties--
SpaceIsAvailable true if the spot is empty or an adversary. SpaceIsMovable true if the spot is your subject and is movable.
When the adversary moves his figure, your freedoms cannot change. Neither SpaceIsAvailable nor SpaceIsMovable will change the value.
If your part is deleted, you simply run the same algorithm, but release the newPosition section.
for d in directions: if (SpaceIsAvailable(position + d)): liberties-- if (SpaceIsMovable(position + d)): liberties++
Now, if liberties > 0 , you have movable parts. All you have to do is track an integer for both players, and you can skip any calculations that determine if any fragments are available.
This does not work if you apply rules prohibiting the repetition of movement. I'm not sure how you are going to implement this. If you do this by finding out which parts cannot move, you can simply compare the total number of freedoms with their freedoms instead of 0 . If it is equal, then no movements are left. If total freedom is lower than the liberties of the parts that cannot move, then something is wrong with my algorithm or your code.
If I read the rules of repetition correctly, there can only be one part at a time that cannot move and therefore only one set of freedoms that you must consider.
frozenLiberties = 0 if (frozenPiece): for d in directions: if (SpaceIsAvailable(frozenPiece + d)): frozenLiberties++ if (liberties > frozenLiberties): // moves available. else: // No moves available.