package org.artisanlogiciel.games.maze.model; import org.artisanlogiciel.games.maze.MovesProvider; import org.artisanlogiciel.games.maze.Position; import org.artisanlogiciel.games.maze.WallsProvider; /** * minimal model without repetition * keep only left and down wall and rely on neightbor squeres to obtain right and up * left down compatible with Bricks * * LEFT 01 * DOWN 10 * * 2 bits for walls * * bit value : * - set : there is a wall , no move in that direction * - unset : move is possible , there is no wall * */ public class HalfSquareRasterModel implements WallsProvider, MovesProvider, WidthHeightProvider, HalfSquareProvider { int LEFT = 0x01; int DOWN = 0x02; // RIGHT 4 // UP 8 // 64 bits for long, 4 bits reserved int USED_BITS = 60; // 2 bits for LEFT UP, ( half square ) int BITSX = 2; int width; int height; long lines[][]; public HalfSquareRasterModel(int width, int height) { this.width = width; this.height = height; lines = new long[height][getLongs()]; } public int getLongs() { return (BITSX * width)/USED_BITS; } public long[][] getLines() { return lines; } public void setLeftDown(int x, int y, short moves) { if (( x < width ) && ( y < height)) { int index = x % (USED_BITS / BITSX); long mask = 0xffffffff ^ ((moves & 0x3) << index); lines[y][(BITSX * x) / USED_BITS] &= mask; } } public void setWalls(int x, int y, short moves) { short walls = (short) ~ moves; setMoves(x,y,moves); } public void setMoves(int x, int y, short moves) { setLeftDown(x,y,moves); // left up setLeftDown(x+1,y,(short) (moves & (LEFT << BITSX))); // right setLeftDown(x,y-1,(short) (moves & (DOWN << BITSX))); // up } public long getLeftDown(int x, int y) { if (( x < width ) && ( y < height)) { // left up long line = lines[y][(BITSX * x) / USED_BITS]; int index = x % (USED_BITS / BITSX); return ((line >> index) & (LEFT | DOWN)); } return 0; } public short getWalls(int x, int y) { return (short) ( getLeftDown(x,y) | ( getLeftDown(x+1,y) & LEFT ) << USED_BITS | // right ( getLeftDown( x, y-1) & DOWN) << USED_BITS // up ); } public short getWalls(Position cell) { return getWalls(cell.getX(), cell.getY()); } public short getMoves(int x, int y) { // moves are where there is no walls ... return (short) ((~ getWalls(x,y)) & 0x0f); } @Override public int getWidth() { return width; } @Override public int getHeight() { return height; } }