//
import java.awt.*; public class test extends BufferedApplet { // DATA FIELDS IN EACH TILE final int TYPE = 0; final int STATE = 1; final int BUG = 2; // TYPES OF TILES final int NIL = 0; final int NW = 1; final int SW = 2; final int SE = 3; final int NE = 4; final int AND = 5; final int OR = 6; final int NTYPES = 7; // STATES OF LOGIC TILES final int N = 1; final int S = 2; final int E = 3; final int W = 4; final int P = 5; final int NSTATES = 6; // BUG DIRECTIONS final int BN = 1; final int BW = 2; final int BS = 4; final int BE = 8; int w = 0, h = 0, ni, nj; Color buttonColor = new Color(255,200,160); Color feltColor = new Color(90,130,90); Color tileColor = new Color(190,150,115); Color bugColor = tileColor.brighter(); int tiles[][][], newTiles[][][]; int mx, my; Rectangle stepRect, runRect; double startTime = 0; public boolean keyUp(Event e, int key) { int i = x2i(mx); int j = y2j(my); int tile[] = tiles[i][j]; int ANDStates[] = {E,W,P}, ORStates[] = {N,S,P}; switch (key) { case '\u03EC': tile[BUG] = BN; break; // UP ARROW case '\u03ED': tile[BUG] = BS; break; // DOWN ARROW case '\u03EE': tile[BUG] = BW; break; // LEFT ARROW case '\u03EF': tile[BUG] = BE; break; // RIGHT ARROW case 127 : tile[BUG] = 0; break; // DELETE case '|' : tile[TYPE] = OR ; tile[STATE] = 0; break; case '-' : tile[TYPE] = AND; tile[STATE] = 0; break; case ' ' : tile[TYPE] = tile[STATE] = 0; break; case '?': for (i = 0 ; i < ni ; i++) for (j = 0 ; j < nj ; j++) { tile = tiles[i][j]; tile[TYPE] = tile[STATE] = tile[BUG] = 0; if ((i+j) % 2 == 0) { tile[TYPE] = AND + random(2); tile[STATE] = (tile[TYPE]==AND ? ANDStates : ORStates)[random(3)]; tile[BUG] = 0; } if (tile[TYPE] == 0 && (i+j) % 2 == 0) tile[TYPE] = 1 + random(4); if (tile[TYPE] == 0) tile[BUG] = 1 + random(4); } break; } damage = true; return true; } java.util.Random R = new java.util.Random(); int random(int n) { return Math.abs(R.nextInt()) % n; } public boolean mouseMove(Event e, int x, int y) { mx = x; my = y; return true; } final int STEP = 0; final int RUN = 1; final int TILES = 2; final int DOWN = 3; final int UP = 4; int mouseState = UP; boolean isRunning = false; public boolean mouseDown(Event e, int x, int y) { if (stepRect.inside(x,y)) mouseState = STEP; else if (runRect.inside(x,y)) mouseState = RUN; else if (x < h) mouseState = TILES; else mouseState = DOWN; damage = true; return true; } public boolean mouseUp(Event e, int x, int y) { switch (mouseState) { case STEP: isRunning = false; step(); break; case RUN: isRunning = ! isRunning; break; case TILES: int i = x2i(x); int j = y2j(y); int type = tiles[i][j][TYPE]; switch (type) { case NIL: type = NE ; break; case NE : type = SE ; break; case SE : type = SW ; break; case SW : type = NW ; break; default : type = NIL; break; } tiles[i][j][TYPE] = type; break; } damage = true; mouseState = UP; return true; } void step() { // IF BUG IS ON A NEGATION, THEN TURN IT 90 DEGREES for (int i = 0 ; i < ni ; i++) for (int j = 0 ; j < nj ; j++) { int tile[] = tiles[i][j]; int bug = tile[BUG]; if (bug != 0) { switch (tile[TYPE]) { case NW: if ((bug&BS)!=0) {bug&=~BS;bug|=BW;} if ((bug&BE)!=0) {bug&=~BE;bug|=BN;} break; case NE: if ((bug&BS)!=0) {bug&=~BS;bug|=BE;} if ((bug&BW)!=0) {bug&=~BW;bug|=BN;} break; case SW: if ((bug&BN)!=0) {bug&=~BN;bug|=BW;} if ((bug&BE)!=0) {bug&=~BE;bug|=BS;} break; case SE: if ((bug&BN)!=0) {bug&=~BN;bug|=BE;} if ((bug&BW)!=0) {bug&=~BW;bug|=BS;} break; } tile[BUG] = bug; } } for (int i = 0 ; i < ni ; i++) for (int j = 0 ; j < nj ; j++) { newTiles[i][j][TYPE ] = tiles[i][j][TYPE]; newTiles[i][j][STATE] = tiles[i][j][STATE]; newTiles[i][j][BUG ] = tiles[i][j][BUG]; } // MOVE BUG TO THE NEXT TILE OVER for (int i = 0 ; i < ni ; i++) for (int j = 0 ; j < nj ; j++) { int tile[] = tiles[i][j]; int newTile[] = newTiles[i][j]; int bug = tile[BUG]; if ((bug&BN)!=0) {newTile[BUG] &= ~BN; setBug(i,j-1, BN);} if ((bug&BS)!=0) {newTile[BUG] &= ~BS; setBug(i,j+1, BS);} if ((bug&BW)!=0) {newTile[BUG] &= ~BW; setBug(i-1,j, BW);} if ((bug&BE)!=0) {newTile[BUG] &= ~BE; setBug(i+1,j, BE);} } for (int i = 0 ; i < ni ; i++) for (int j = 0 ; j < nj ; j++) { tiles[i][j][STATE] = newTiles[i][j][STATE]; tiles[i][j][BUG ] = newTiles[i][j][BUG ]; } } void setBug(int i, int j, int bug) { i = (i + ni) % ni; j = (j + nj) % nj; int tile[] = newTiles[i][j]; int state = tile[STATE]; bug = tile[BUG] | bug; switch (tile[TYPE]) { case OR: switch (state) { case 0: switch (bug) { case BN: state = N; bug = 0; break; case BS: state = S; bug = 0; break; case BE: state = P; bug = 0; break; case BW: state = P; bug = 0; break; case BN|BE: case BN|BW: case BS|BE: case BS|BW: bug = BN|BS; break; case BN|BS|BE: case BN|BE|BW: state = N; bug = BN|BS; break; case BN|BS|BW: case BS|BE|BW: state = S; bug = BN|BS; break; } break; case N: case S: if (bug != 0 && bug != (BN|BS|BE|BW)) state = 0; switch (bug) { case BN: case BS: case BE: case BW: bug = BN|BS; break; case BN|BS: case BN|BE: case BS|BE: bug = BN|BS|BE; break; case BE|BW: case BN|BW: case BS|BW: bug = BN|BS|BW; break; case BN|BS|BE: case BN|BS|BW: case BN|BE|BW: case BS|BE|BW: bug = BN|BS|BE|BW; break; } break; case P: if (bug != 0 && bug != (BN|BS|BE|BW)) state = 0; switch (bug) { case BN: case BS: bug = BN|BS; break; case BE: case BW: bug = BE|BW; break; case BN|BS: case BN|BE: case BS|BE: bug = BN|BS|BE; break; case BN|BW: case BS|BW: bug = BN|BS|BW; break; case BE|BW: bug = BE|BW|BN; break; case BN|BS|BE: case BN|BS|BW: case BN|BE|BW: case BS|BE|BW: bug = BN|BS|BE|BW; break; } break; } break; case AND: switch (state) { case 0: switch (bug) { case BN: case BS: state = P; bug = 0; break; case BE: state = E; bug = 0; break; case BW: state = W; bug = 0; break; } break; case P: switch (bug) { case BN: case BS: state = 0; bug = BN|BS; break; case BE: case BW: state = 0; bug = BE|BW; break; } break; case E: case W: switch (bug) { case BN: case BS: case BE: case BW: state = 0; bug = BE|BW; break; } break; } break; // IF ANOTHER BUG IS ALSO COMING IN, SQUEEZE THEM BOTH INTO THIS TILE default: switch (tile[BUG]) { case BE: switch (bug) { case BW: bug = BE|BW; break; case BN: bug = BN|BE; break; case BS: bug = BS|BE; break; } case BW: switch (bug) { case BE: bug = BE|BW; break; case BN: bug = BN|BW; break; case BS: bug = BS|BW; break; } case BN: switch (bug) { case BS: bug = BN|BS; break; case BE: bug = BN|BE; break; case BW: bug = BN|BW; break; } case BS: switch (bug) { case BN: bug = BN|BS; break; case BE: bug = BS|BE; break; case BW: bug = BS|BW; break; } } break; } tile[STATE] = state; tile[BUG] = bug; } int clicks = 0; public void render(Graphics g) { if (w == 0) { w = bounds().width; h = bounds().height; ni = h/32; nj = h/32; tiles = new int[ni][nj][3]; newTiles = new int[ni][nj][3]; stepRect = new Rectangle(w - 16 - 40, 16, 40, 20); runRect = new Rectangle(stepRect.x, stepRect.y + stepRect.height + 16, stepRect.width, stepRect.height); } if (isRunning) { double time = System.currentTimeMillis() / 1000.; if (startTime == 0) startTime = time; int newClicks = (int)(4 * (time - startTime)); if (newClicks > clicks) { step(); clicks = newClicks; } } g.setColor(feltColor); g.fillRect(0,0,w,h); g.setColor(buttonColor); g.fill3DRect(stepRect.x, stepRect.y, stepRect.width, stepRect.height, mouseState != STEP); g.setColor(Color.black); g.drawString("STEP", stepRect.x + 4, stepRect.y + 15); g.setColor(buttonColor); g.fill3DRect(runRect.x, runRect.y, runRect.width, runRect.height, mouseState != RUN); g.setColor(Color.black); g.drawString(isRunning ? "STOP" : "RUN", runRect.x + 4, runRect.y + 15); g.setColor(Color.black); for (int i = 0 ; i <= ni ; i++) g.drawLine(i2x(i)-16,0,i2x(i)-16,h); for (int j = 0 ; j <= nj ; j++) g.drawLine(0,j2y(j)-16,h,j2y(j)-16); for (int i = 0 ; i < ni ; i++) for (int j = 0 ; j < nj ; j++) { int tile[] = tiles[i][j]; int type = tile[TYPE]; int state = tile[STATE]; int bug = tile[BUG]; drawTile(g, type, state, i2x(i), j2y(j)); switch (type) { case NW: if (bug==BS) bug = BS|BW; else if (bug==BE) bug = BN|BE; break; case NE: if (bug==BS) bug = BS|BE; else if (bug==BW) bug = BN|BW; break; case SW: if (bug==BN) bug = BN|BW; else if (bug==BE) bug = BS|BE; break; case SE: if (bug==BN) bug = BN|BE; else if (bug==BW) bug = BS|BW; break; } drawBug(g, bug, i2x(i), j2y(j)); } animating = isRunning; } int i2x(int i) { return 16 + 32 * i; } int j2y(int j) { return 16 + 32 * j; } int x2i(int x) { return x / 32; } int y2j(int y) { return y / 32; } void drawTile(Graphics g, int type, int state, int x, int y) { g.setColor(tileColor.darker()); g.fillRect(x - 13, y - 13, 29, 29); g.setColor(tileColor.brighter()); g.fillRect(x - 15, y - 15, 30, 30); g.setColor(tileColor); g.fillRect(x - 14, y - 14, 29, 29); g.setColor(Color.black); switch (type) { case NE: g.fillRect(x-5,y+2, 8,3); g.fillRect(x-5,y-3, 3,8); break; case NW: g.fillRect(x-3,y+2, 8,3); g.fillRect(x+2,y-3, 3,8); break; case SE: g.fillRect(x-5,y-5, 8,3); g.fillRect(x-5,y-5, 3,8); break; case SW: g.fillRect(x-3,y-5, 8,3); g.fillRect(x+2,y-5, 3,8); break; case AND: switch (state) { case 0: g.fillRect(x-7,y-1,15,3); break; case E: drawTriangle(g,x-7,y-7,x-7,y+7,x+7,y); break; case W: drawTriangle(g,x+7,y-7,x+7,y+7,x-7,y); break; case P: g.drawLine(x-4,y,x+4,y); break; } break; case OR: switch (state) { case 0: g.fillRect(x-1,y-7,3,15); break; case S: drawTriangle(g,x-7,y-7,x+7,y-7,x,y+7); break; case N: drawTriangle(g,x-7,y+7,x+7,y+7,x,y-7); break; case P: g.drawLine(x,y-4,x,y+4); break; } break; } } void drawTriangle(Graphics g, int ax,int ay,int bx,int by,int cx,int cy) { int X[] = {ax,bx,cx}, Y[] = {ay,by,cy}; g.drawPolygon(X,Y,3); } void drawBug(Graphics g, int bug, int x, int y) { switch (bug) { case BE|BW|BN: case BN: drawBug(g,x-8,y+9,x+8,y+9,x,y-9); break; case BE|BW|BS: case BS: drawBug(g,x-8,y-9,x+8,y-9,x,y+9); break; case BN|BS|BE: case BE: drawBug(g,x-9,y-8,x-9,y+8,x+9,y); break; case BN|BS|BW: case BW: drawBug(g,x+9,y-8,x+9,y+8,x-9,y); break; case BN|BE: drawBug(g,x-10,y-2,x+2,y+10,x+8,y-8); break; case BS|BE: drawBug(g,x-10,y+2,x+2,y-10,x+8,y+8); break; case BN|BW: drawBug(g,x+10,y-2,x-2,y+10,x-8,y-8); break; case BS|BW: drawBug(g,x+10,y+2,x-2,y-10,x-8,y+8); break; case BN|BS: drawBug(g,x-8,y-1,x+8,y-1,x,y-10); drawBug(g,x-8,y+1,x+8,y+1,x,y+10); break; case BE|BW: drawBug(g,x+1,y-8,x+1,y+8,x+10,y); drawBug(g,x-1,y-8,x-1,y+8,x-10,y); break; } } void xdrawBug(Graphics g, int ax,int ay,int bx,int by,int cx,int cy) { int x = (ax+bx+cx) / 3, y = (ay+by+cy) / 3; x = x / 32 * 32 + 16; y = y / 32 * 32 + 16; g.setColor(tileColor.brighter()); g.fill3DRect(x-12,y-12,24,24,true); int X[] = {ax,bx,cx}, Y[] = {ay,by,cy}; g.setColor(Color.black); g.fillPolygon(X,Y,3); g.drawPolygon(X,Y,3); } void drawBug(Graphics g, int ax,int ay,int bx,int by,int cx,int cy) { int x = (2*ax+2*bx+cx)/5, y = (2*ay+2*by+cy)/5; int X[] = {ax,x,bx,cx}, Y[] = {ay,y,by,cy}; draw(g, X,Y, 1, 1,Color.black); draw(g, X,Y,-1,-1,bugColor.brighter()); draw(g, X,Y, 0, 0,bugColor); } void draw(Graphics g, int X[], int Y[], int dx, int dy, Color color) { for (int i = 0 ; i < X.length ; i++) { X[i] += dx; Y[i] += dy; } g.setColor(color); g.fillPolygon(X,Y,X.length); g.drawPolygon(X,Y,Y.length); for (int i = 0 ; i < X.length ; i++) { X[i] -= dx; Y[i] -= dy; } } }