/* Bridges Source Code */
/* By Dick Christoph April 1998 */
/* dchristo@minn.net */
/* www1.minn.net/~dchristo */
import java.applet.*;
import java.awt.*;
import java.io.*;
public class Bridges extends Applet {
public static final int MAXSCREENX = 340;
public static final int MAXSCREENY = 340;
public static final int MAXROWS = 17;
public static final int MAXCOLS = 17;
public static final int NOTOWER = 0;
public static final int BLUETOWER = 1, BLUE = 1;
public static final int REDTOWER = 2, RED = 2;
public static final int ROW = 0;
public static final int COL = 1;
public static final int UP = 1;
public static final int RIGHT = 2;
public static final int LEFT = 3;
public static final int DOWN = 4;
public static int board[][], whoseTurn;
static BridgeCanvas cnv1;
static Label turnMsg, statusMsg;
Button newGameButton;
Panel p, p1;
static boolean redWins, blueWins, debug;
public static final int MAXSTEPS = 10000;
public static final int MAXOPTIONS = 200;
public static final int MAXPATHLIST = 32;
public static boolean visited[][];
public static boolean consider[][];
public static Option optionList[];
public static Step steps[];
public static int minSteps[][];
public static PathList bluePathList[], redPathList[];
public static int optionTop, firstFreeStep, bluePathListTop, redPathListTop;
public static double stepCounter;
public static double maxSteps, maxOptions, maxPathList, maxMoves;
public void init()
{
setLayout(null);
resize(MAXSCREENX,MAXSCREENY+60);
addNotify();
debug = false;
cnv1 = new BridgeCanvas();
add(cnv1);
cnv1.reshape(0,0,MAXSCREENX, MAXSCREENY);
p = new Panel();
turnMsg = new Label("");
turnMsg.setAlignment(Label.CENTER);
p.add(turnMsg);
whoseTurn = BLUE;
toggleTurnMsg();
p.reshape(0,MAXSCREENY,MAXSCREENX,30);
add(p);
p1 = new Panel();
newGameButton = new Button("New Game");
p1.add(newGameButton);
if (debug)
{ statusMsg = new Label("");
statusMsg.setAlignment(Label.CENTER);
p1.add(statusMsg);
}
p1.reshape(0,MAXSCREENY+30,MAXSCREENX,30);
add(p1);
initBoard();
setupMem();
cnv1.repaint();
}
public boolean action(Event e, Object arg)
{ Object source = e.target;
if (source == newGameButton)
{ initBoard();
cnv1.repaint();
}
return true;
}
public void destroy() {
}
public void initBoard()
{ int r, c;
redWins = false;
blueWins = false;
whoseTurn = BLUE;
toggleTurnMsg();
if (debug)
statusMsg.setText("");
maxSteps = 0;
maxOptions = 0;
maxPathList = 0;
maxMoves = 0;
board = new int[MAXROWS][MAXCOLS];
for (r = 0; r < MAXROWS; r++)
{ for (c = 0; c < MAXCOLS; c++)
{ board[r][c] = NOTOWER;
if ((r % 2) == 0) /* even row */
{ if ((c % 2) == 1) /* odd col */
{ board[r][c] = BLUETOWER;
} }
else /* odd row */
{ if ((c % 2) == 0) /* even col */
{ board[r][c] = REDTOWER;
} } } }
}
public static void toggleTurnMsg()
{
if (whoseTurn == BLUE)
{ whoseTurn = RED;
turnMsg.setText("Red - It is your Move");
}
else
{ whoseTurn = BLUE;
turnMsg.setText("Blue - It is your Move");
}
}
public static boolean toggleBox(int r, int c)
{ boolean rv;
if (board[r][c] == NOTOWER)
{ rv = true;
if (whoseTurn == BLUE)
{ board[r][c] = BLUETOWER;
toggleTurnMsg();
determineBlueProgress();
}
else
{ board[r][c] = REDTOWER;
toggleTurnMsg();
determineRedProgress();
}
}
else
rv = false;
return(rv);
}
public static void determineBlueProgress()
{ int r,c, r1, c1, tryTop, tryPtr;
int tries[][];
visited = new boolean[MAXROWS][MAXCOLS];
for (r = 0; r < MAXROWS; r++)
for (c = 0; c < MAXCOLS; c++)
visited[r][c] = false;
tries = new int[MAXROWS*MAXCOLS][2];
blueWins = false;
r = 0;
for (c = 1; c < MAXCOLS && (!blueWins); c = c + 2)
{ /* board[0][c] = BLUETOWER */
if (!visited[0][c])
{ tryTop = 0;
tryPtr = 0;
tries[tryTop][ROW] = 0;
tries[tryTop++][COL] = c;
while ((tryPtr < tryTop) && (!blueWins))
{ r1 = tries[tryPtr][ROW];
c1 = tries[tryPtr][COL];
visited[r1][c1] = true;
if (r1 == MAXROWS - 1)
blueWins = true;
else
{ if ((r1 - 1) >= 0) /* check up */
{ if ((!visited[r1-1][c1]) && (board[r1-1][c1] == BLUETOWER))
{ tries[tryTop][ROW] = r1-1;
tries[tryTop++][COL] = c1;
} }
/* check down */
if ((!visited[r1+1][c1]) && (board[r1+1][c1] == BLUETOWER))
{ { tries[tryTop][ROW] = r1+1;
tries[tryTop++][COL] = c1;
} }
if ((c1 - 1) >= 0) /* check left */
{ if ((!visited[r1][c1-1]) && (board[r1][c1-1] == BLUETOWER))
{ tries[tryTop][ROW] = r1;
tries[tryTop++][COL] = c1-1;
} }
/* check right */
if ((c1 + 1) < MAXCOLS)
{ if ((!visited[r1][c1+1]) && (board[r1][c1+1] == BLUETOWER))
{ tries[tryTop][ROW] = r1;
tries[tryTop++][COL] = c1+1;
} } }
tryPtr++;
}
}
}
if (blueWins)
{ turnMsg.setText("Blue Wins");
if (debug)
statusMsg.setText("Blue Wins" + " MS: " + maxSteps + " MO: " + maxOptions + " MP: " + maxPathList + " MM: " + maxMoves);
}
}
public static void determineRedProgress()
{ int r,c, r1, c1, tryTop, tryPtr;
int tries[][];
visited = new boolean[MAXROWS][MAXCOLS];
for (r = 0; r < MAXROWS; r++)
for (c = 0; c < MAXCOLS; c++)
visited[r][c] = false;
tries = new int[MAXROWS*MAXCOLS][2];
redWins = false;
c = 0;
for (r = 1; r < MAXROWS && (!redWins); r = r + 2)
{ /* board[r][0] = REDTOWER */
if (!visited[r][0])
{ tryTop = 0;
tryPtr = 0;
tries[tryTop][ROW] = r;
tries[tryTop++][COL] = 0;
while ((tryPtr < tryTop) && (!redWins))
{ r1 = tries[tryPtr][ROW];
c1 = tries[tryPtr][COL];
visited[r1][c1] = true;
if (c1 == MAXCOLS - 1)
redWins = true;
else
{ if ((r1 - 1) >= 0) /* check up */
{ if ((!visited[r1-1][c1]) && (board[r1-1][c1] == REDTOWER))
{ tries[tryTop][ROW] = r1-1;
tries[tryTop++][COL] = c1;
} }
if ((r1 + 1) < MAXROWS) /* check down */
{ if ((!visited[r1+1][c1]) && (board[r1+1][c1] == REDTOWER))
{ tries[tryTop][ROW] = r1+1;
tries[tryTop++][COL] = c1;
} }
if ((c1 - 1) >= 0) /* check left */
{ if ((!visited[r1][c1-1]) && (board[r1][c1-1] == REDTOWER))
{ tries[tryTop][ROW] = r1;
tries[tryTop++][COL] = c1-1;
} }
/* check right */
if ((c1 + 1) < MAXCOLS)
{ if ((!visited[r1][c1+1]) && (board[r1][c1+1] == REDTOWER))
{ tries[tryTop][ROW] = r1;
tries[tryTop++][COL] = c1+1;
} } }
tryPtr++;
}
}
}
if (redWins)
{ turnMsg.setText("Red Wins");
if (debug)
statusMsg.setText("Red Wins" + " MS: " + maxSteps + " MO: " + maxOptions + " MP: " + maxPathList + " MM: " + maxMoves);
} }
public static void setupMem()
{ int i;
steps = new Step[MAXSTEPS];
for (i = 0; i < MAXSTEPS; i++)
steps[i] = new Step();
optionList = new Option[MAXOPTIONS];
for (i = 0; i < MAXOPTIONS; i++)
optionList[i] = new Option();
bluePathList = new PathList[MAXPATHLIST];
for (i = 0; i < MAXPATHLIST; i++)
bluePathList[i] = new PathList();
redPathList = new PathList[MAXPATHLIST];
for (i = 0; i < MAXPATHLIST; i++)
redPathList[i] = new PathList();
}
public static void findBestMove()
{ int i, r, c, pth, stp, s, curStep, row, col;
Point bestMove;
stepCounter = 0;
for (i = 0; i < MAXSTEPS; i++)
steps[i].nextStep = i + 1;
steps[MAXSTEPS-1].nextStep = -1;
firstFreeStep = 0;
visited = new boolean[MAXROWS][MAXCOLS];
minSteps = new int[MAXROWS][MAXCOLS];
consider = new boolean[MAXROWS][MAXCOLS];
for (r = 0; r < MAXROWS; r++)
{ for (c = 0; c < MAXCOLS; c++)
{ visited[r][c] = false;
minSteps[r][c] = MAXROWS * MAXCOLS;
if ((r == 0) || (r == MAXROWS-1) || (c == 0) || (c == MAXCOLS-1))
consider[r][c] = false;
else
consider[r][c] = true;
}
}
optionTop = 0;
bluePathListTop = 0;
findShortestBluePaths();
for (r = 0; r < MAXROWS; r++)
{ for (c = 0; c < MAXCOLS; c++)
{ visited[r][c] = false;
minSteps[r][c] = MAXROWS * MAXCOLS;
if ((r == 0) || (r == MAXROWS-1) || (c == 0) || (c == MAXCOLS-1))
consider[r][c] = false;
else
consider[r][c] = true;
}
}
optionTop = 0;
redPathListTop = 0;
findShortestRedPaths();
if (debug)
statusMsg.setText("BPLT: " + bluePathListTop + " RPLT: " + redPathListTop + " SC: " + stepCounter + " MS: " + maxSteps);
bestMove = compareBlueAndRedLists();
row = bestMove.y;
col = bestMove.x;
toggleBox(row,col);
cnv1.repaint();
}
public static final int COUNT = 2, CLOSEST = 3;
public static final int MAXDIST = MAXROWS * MAXCOLS;
public static Point compareBlueAndRedLists()
{ int blueList[][], redList[][], tempBoard[][][], moveList[][];
int blueTop, redTop, cmp, b, r, c, p, row, col, cp, lp, i, j;
int close, closeCnt, lo, hi, mid, maxCount, count, moveListTop;
boolean found, secureTop, secureBottom;
Point rv;
rv = new Point(0,0);
secureTop = false;
secureBottom = false;
for (c = 1; c < MAXCOLS; c+=2)
{ if (board[1][c] == BLUETOWER)
secureTop = true;
if (board[MAXROWS-2][c] == BLUETOWER)
secureBottom = true;
}
if ((!secureTop) || (!secureBottom))
{ if (!secureTop)
{ for (b = 0; (b <= 6) && (!secureTop); b += 2)
{ for (c = 7-b; c <= 9+b; c += 2)
{ if (board[1][c] == NOTOWER)
{ rv.x = c;
rv.y = 1;
secureTop = true;
} } } }
else
{ for (b = 0; (b <= 6) && (!secureBottom); b += 2)
{ for (c = 7-b; c <= 9+b; c += 2)
{ if (board[MAXROWS-2][c] == NOTOWER)
{ rv.x = c;
rv.y = MAXROWS-2;
secureBottom = true;
} } } } }
else
{
if ((redPathList[0].togo == 1) && (bluePathList[0].togo > 1))
{ /* Red has only one togo, must block it */
cp = redPathList[0].firstStep;
rv.x = -1;
while ((cp != -1) && (rv.x == -1))
{ row = steps[cp].row;
col = steps[cp].col;
if (board[row][col] == NOTOWER)
{ rv.x = col;
rv.y = row;
}
cp = steps[cp].nextStep;
}
}
else
{ blueList = new int[MAXROWS*MAXCOLS][3];
redList = new int[MAXROWS*MAXCOLS][4];
tempBoard = new int[MAXROWS][MAXCOLS][2]; /* 0 = COUNT 1 = CLOSEST */
moveList = new int[MAXROWS*MAXCOLS][2];
for (r = 0; r < MAXROWS; r++)
{ for (c = 0; c < MAXCOLS; c++)
{ tempBoard[r][c][0] = 0;
tempBoard[r][c][1] = 0;
} }
for (p = 0; p < bluePathListTop; p++)
{ cp = bluePathList[p].firstStep;
while (cp != -1)
{ row = steps[cp].row;
col = steps[cp].col;
if (board[row][col] == NOTOWER)
{ tempBoard[row][col][0] += 1;
}
cp = steps[cp].nextStep;
} }
blueTop = 0;
for (r = 0; r < MAXROWS; r++)
{ for (c = 0; c < MAXCOLS; c++)
{ if (tempBoard[r][c][0] != 0)
{ blueList[blueTop][ROW] = r;
blueList[blueTop][COL] = c;
blueList[blueTop++][COUNT] = tempBoard[r][c][0];
} } }
for (r = 0; r < MAXROWS; r++)
{ for (c = 0; c < MAXCOLS; c++)
{ tempBoard[r][c][0] = 0;
tempBoard[r][c][1] = MAXDIST;
} }
lp = -1;
for (p = 0; p < redPathListTop; p++)
{ cp = redPathList[p].firstStep;
steps[cp].prevStep = -1; /* This should have been taken care of elsewhere */
closeCnt = MAXDIST;
while (cp != -1)
{ row = steps[cp].row;
col = steps[cp].col;
if (board[row][col] == NOTOWER)
{ tempBoard[row][col][0] += 1;
tempBoard[row][col][1] = Math.min(tempBoard[row][col][1], closeCnt++);
}
else
closeCnt = 1;
lp = cp;
cp = steps[cp].nextStep;
}
closeCnt = MAXDIST;
while (lp != -1)
{ row = steps[lp].row;
col = steps[lp].col;
if (board[row][col] == NOTOWER)
{ tempBoard[row][col][0] += 1;
tempBoard[row][col][1] = Math.min(tempBoard[row][col][1], closeCnt++);
}
else
closeCnt = 1;
lp = steps[lp].prevStep;
}
}
redTop = 0;
for (r = 0; r < MAXROWS; r++)
{ for (c = 0; c < MAXCOLS; c++)
{ if (tempBoard[r][c][0] != 0)
{ redList[redTop][ROW] = r;
redList[redTop][COL] = c;
redList[redTop][COUNT] = tempBoard[r][c][0] / 2;
redList[redTop++][CLOSEST] = tempBoard[r][c][1];
} } }
for (i = 0; i < blueTop-1; i++)
{ for (j = i; j < blueTop; j++)
{ cmp = compareRowCol(blueList[i][ROW], blueList[i][COL], blueList[j][ROW], blueList[j][COL]);
if (cmp == 1)
{ row = blueList[j][ROW];
col = blueList[j][COL];
count = blueList[j][COUNT];
blueList[j][ROW] = blueList[i][ROW];
blueList[j][COL] = blueList[i][COL];
blueList[j][COUNT] = blueList[i][COUNT];
blueList[i][ROW] = row;
blueList[i][COL] = col;
blueList[i][COUNT] = count;
} } }
for (i = 0; i < redTop-1; i++)
{ for (j = i; j < redTop; j++)
{ cmp = compareCloseRowCol(redList[i][CLOSEST], redList[i][ROW], redList[i][COL], redList[j][CLOSEST], redList[j][ROW], redList[j][COL]);
if (cmp == 1)
{ row = redList[j][ROW];
col = redList[j][COL];
count = redList[j][COUNT];
close = redList[j][CLOSEST];
redList[j][ROW] = redList[i][ROW];
redList[j][COL] = redList[i][COL];
redList[j][COUNT] = redList[i][COUNT];
redList[j][CLOSEST] = redList[i][CLOSEST];
redList[i][ROW] = row;
redList[i][COL] = col;
redList[i][COUNT] = count;
redList[i][CLOSEST] = close;
} } }
r = 0;
b = 0;
found = false;
rv.x = -1;
maxCount = 0;
close = MAXDIST;
moveListTop = 0;
while ((r < redTop) && (!found))
{ /* binsearch bluelist for redList[r][ROW]{COL] */
lo = 0;
hi = blueTop - 1;
mid = 0;
while ((lo <= hi) && (!found))
{ mid = (lo + hi) / 2;
cmp = compareRowCol(redList[r][ROW], redList[r][COL], blueList[mid][ROW], blueList[mid][COL]);
if (cmp > 0)
lo = mid + 1;
else
if (cmp == 0)
found = true;
else
hi = mid - 1;
}
if (found)
{ /* All those in moveList will have same Count and Closeness */
if ( (blueList[mid][COUNT] + redList[mid][COUNT] >= maxCount)
&& (redList[r][CLOSEST] <= close))
{ if ( (blueList[mid][COUNT] + redList[mid][COUNT] > maxCount)
|| (redList[r][CLOSEST] < close))
moveListTop = 0;
moveList[moveListTop][ROW] = blueList[mid][ROW];
moveList[moveListTop++][COL] = blueList[mid][COL];
maxCount = blueList[mid][COUNT];
close = redList[r][CLOSEST];
}
found = false;
}
r++;
}
if (moveListTop == 0)
{ for (b = 0; b < blueTop; b++)
{ if (blueList[b][COUNT] >= maxCount)
{ if (blueList[b][COUNT] > maxCount)
moveListTop = 0;
moveList[moveListTop][ROW] = blueList[b][ROW];
moveList[moveListTop++][COL] = blueList[b][COL];
maxCount = blueList[b][COUNT];
} } }
maxMoves = Math.max(moveListTop, maxMoves);
b = (int) (Math.random() * moveListTop);
rv.x = moveList[b][COL];
rv.y = moveList[b][ROW];
} }
return(rv);
}
/* Returns -1 if row1,col1 < row2, col2 0 if equal +1 if greater */
public static int compareCloseRowCol(int close1, int row1, int col1, int close2, int row2, int col2)
{ int rc1, rc2;
rc1 = (close1 * 2000) + (row1 * 50) + col1;
rc2 = (close2 * 2000) + (row2 * 50) + col2;
if (rc1 == rc2)
return(0);
else
if (rc1 < rc2)
return(-1);
else
return(+1);
}
/* Returns -1 if row1,col1 < row2, col2 0 if equal +1 if greater */
public static int compareRowCol(int row1, int col1, int row2, int col2)
{ int rc1, rc2;
rc1 = (row1 * 100) + col1;
rc2 = (row2 * 100) + col2;
if (rc1 == rc2)
return(0);
else
if (rc1 < rc2)
return(-1);
else
return(+1);
}
public static int newStep()
{ int rv;
rv = firstFreeStep;
stepCounter++;
maxSteps = Math.max(stepCounter, maxSteps);
firstFreeStep = steps[firstFreeStep].nextStep;
if (firstFreeStep == -1)
{ if (debug)
{ statusMsg.setText("Out of Memory for Steps.");
System.out.println("StepCounter: " + stepCounter);
}
else
turnMsg.setText("Out of Memory for Steps.");
}
steps[rv].nextStep = -1;
return(rv);
}
public static void deleteStep(int stepNum)
{
stepCounter--;
steps[stepNum].nextStep = firstFreeStep;
firstFreeStep = stepNum;
}
public static void findShortestBluePaths()
{ int pathHead, pathHeadLength, pathHeadTogo, minTogo, c, row, col;
int stepCnt, prevStep, nextStep, curStep, lastStep, targ, cp, lp;
int row1, col1, ph, pathCnt, c1;
minTogo = MAXROWS * MAXCOLS;
pathCnt = 0;
for (c = 1; c < MAXCOLS - 1; c+=2)
{ // System.out.println("Column: " + c);
/* No need to consider row1 except for column c */
for (c1 = 1; c1 < MAXCOLS - 1; c1+= 2)
{ if (c1 != c)
consider[1][c1] = false;
else
consider[1][c1] = true;
}
if (board[1][c] != REDTOWER)
{ curStep = newStep();
pathHead = curStep;
steps[curStep].row = 1;
steps[curStep].col = c;
steps[curStep].stepCnt = 1;
steps[curStep].direction = DOWN;
steps[curStep].nextStep = -1;
steps[curStep].prevStep = -1;
pathHeadLength = 1;
if (board[1][c] == NOTOWER)
pathHeadTogo = 1;
else
pathHeadTogo = 0;
visited[1][c] = true;
optionTop = 0;
row1 = 2;
col1 = c;
stepCnt = 2;
/* check right */
considerBlueMove(stepCnt, row1, col1+1, RIGHT);
/* check LEFT */
considerBlueMove(stepCnt, row1, col1-1, LEFT);
/* check DOWN */
considerBlueMove(stepCnt, row1+1, col1, DOWN);
lastStep = curStep;
stepCnt = 3;
while (optionTop > 0)
{ optionTop--;
/* makeMove(optionList[optionTop]); */
while (optionList[optionTop].stepCnt <= steps[lastStep].stepCnt)
{ row = steps[lastStep].row;
col = steps[lastStep].col;
visited[row][col] = false;
pathHeadLength--;
if (board[row][col] != BLUETOWER)
pathHeadTogo--;
lastStep = steps[lastStep].prevStep;
deleteStep(steps[lastStep].nextStep);
steps[lastStep].nextStep = -1;
}
curStep = newStep();
steps[lastStep].nextStep = curStep;
steps[curStep].prevStep = lastStep;
steps[curStep].row = optionList[optionTop].row;
steps[curStep].col = optionList[optionTop].col;
steps[curStep].stepCnt = optionList[optionTop].stepCnt;
steps[curStep].direction = optionList[optionTop].direction;
steps[curStep].nextStep = -1;
pathHeadLength++;
row = steps[curStep].row;
col = steps[curStep].col;
if (board[row][col] == NOTOWER)
pathHeadTogo++;
visited[row][col] = true;
if ((steps[curStep].row == MAXROWS - 2)
|| (pathHeadTogo > minTogo)
|| (pathHeadTogo > minSteps[row][col]))
{ if ( (steps[curStep].row == MAXROWS - 2)
&& (pathHeadTogo <= minTogo))
{ /* savePath(); */
if (pathHeadTogo < minTogo) /* replace current shortest path(s) */
{ deleteBluePathList();
targ = 0;
bluePathListTop = 1;
minTogo = pathHeadTogo;
}
else /* path HeadTogo = minTogo */
{ if (bluePathListTop < MAXPATHLIST) /* add to list of shortest path(s) */
{ targ = bluePathListTop++;
maxPathList = Math.max(bluePathListTop, maxPathList);
}
else
targ = MAXPATHLIST;
}
if (targ == MAXPATHLIST)
{ if (debug)
statusMsg.setText("Out of space for Blue PathList");
else
turnMsg.setText("");
}
else
{ cp = newStep();
bluePathList[targ].length = pathHeadLength;
bluePathList[targ].togo = pathHeadTogo;
bluePathList[targ].firstStep = cp;
steps[cp].row = steps[pathHead].row;
steps[cp].col = steps[pathHead].col;
steps[cp].stepCnt = steps[pathHead].stepCnt;
steps[cp].direction = steps[pathHead].direction;
ph = steps[pathHead].nextStep;
lp = cp;
while (ph != -1)
{ cp = newStep();
steps[lp].nextStep = cp;
steps[cp].prevStep = lp;
steps[cp].row = steps[ph].row;
steps[cp].col = steps[ph].col;
steps[cp].stepCnt = steps[ph].stepCnt;
steps[cp].direction = steps[ph].direction;
ph = steps[ph].nextStep;
lp = cp;
}
steps[lp].nextStep = -1;
/* Be sure pointers are left in right state for recursion */
} }
/* else bailout */
}
else /* keep going */
{ minSteps[row][col] = pathHeadTogo;
switch (steps[curStep].direction) /* ROW1, COL1 is location of initial BLUETOWER */
{ case UP:
row1 = steps[curStep].row - 1;
col1 = steps[curStep].col;
break;
case DOWN:
row1 = steps[curStep].row + 1;
col1 = steps[curStep].col;
break;
case LEFT:
row1 = steps[curStep].row;
col1 = steps[curStep].col-1;
break;
case RIGHT:
row1 = steps[curStep].row;
col1 = steps[curStep].col+1;
break;
}
stepCnt = steps[curStep].stepCnt + 1;
/* check UP */
considerBlueMove(stepCnt, row1-1, col1, UP);
/* check right */
considerBlueMove(stepCnt, row1, col1+1, RIGHT);
/* check LEFT */
considerBlueMove(stepCnt, row1, col1-1, LEFT);
/* check DOWN */
considerBlueMove(stepCnt, row1+1, col1, DOWN);
}
lastStep = curStep;
} /* End While (optionTop > 0) */
while (lastStep != -1)
{ row = steps[lastStep].row;
col = steps[lastStep].col;
visited[row][col] = false;
lp = steps[lastStep].prevStep;
deleteStep(lastStep);
lastStep = lp;
}
} /* end if board[1][c] != REDTOWER */
} /* End for c = 1 to MAXCOLS */
}
public static void deleteBluePathList()
{ int p, lp, cp;
for (p = 0; p < bluePathListTop; p++)
{ cp = bluePathList[p].firstStep;
while (cp != -1)
{ lp = cp;
cp = steps[cp].nextStep;
deleteStep(lp);
}
}
bluePathListTop = 0;
}
public static void considerBlueMove(int stepCnt, int row2, int col2, int direction)
{
if ((consider[row2][col2])
&& (!visited[row2][col2])
&& (board[row2][col2] != REDTOWER) )
{ optionList[optionTop].stepCnt = stepCnt;
optionList[optionTop].row = row2;
optionList[optionTop].col = col2;
optionList[optionTop].direction = direction;
optionTop++;
maxOptions = Math.max(optionTop, maxOptions);
}
}
public static void findShortestRedPaths()
{ int pathHead, pathHeadLength, pathHeadTogo, minTogo, row, col;
int stepCnt, prevStep, nextStep, curStep, lastStep, targ, cp, lp;
int row1, col1, ph, pathCnt, r, r1;
minTogo = MAXROWS * MAXCOLS;
pathCnt = 0;
for (r = 1; r < MAXROWS - 1; r+=2)
{ // System.out.println("Row: " + r);
/* No need to consider col1 except for row r */
for (r1 = 1; r1 < MAXROWS - 1; r1+= 2)
{ if (r1 != r)
consider[r1][1] = false;
else
consider[r1][1] = true;
}
if (board[r][1] != BLUETOWER)
{ curStep = newStep();
pathHead = curStep;
steps[curStep].row = r;
steps[curStep].col = 1;
steps[curStep].stepCnt = 1;
steps[curStep].direction = RIGHT;
steps[curStep].nextStep = -1;
steps[curStep].prevStep = -1;
pathHeadLength = 1;
if (board[r][1] == NOTOWER)
pathHeadTogo = 1;
else
pathHeadTogo = 0;
visited[r][1] = true;
optionTop = 0;
row1 = r;
col1 = 2;
stepCnt = 2;
/* check UP */
considerRedMove(stepCnt, row1-1, col1, UP);
/* check DOWN */
considerRedMove(stepCnt, row1+1, col1, DOWN);
/* check right */
considerRedMove(stepCnt, row1, col1+1, RIGHT);
lastStep = curStep;
stepCnt = 3;
while (optionTop > 0)
{ optionTop--;
/* makeMove(optionList[optionTop]); */
while (optionList[optionTop].stepCnt <= steps[lastStep].stepCnt)
{ row = steps[lastStep].row;
col = steps[lastStep].col;
visited[row][col] = false;
pathHeadLength--;
if (board[row][col] != REDTOWER)
pathHeadTogo--;
lastStep = steps[lastStep].prevStep;
deleteStep(steps[lastStep].nextStep);
steps[lastStep].nextStep = -1;
}
curStep = newStep();
steps[lastStep].nextStep = curStep;
steps[curStep].prevStep = lastStep;
steps[curStep].row = optionList[optionTop].row;
steps[curStep].col = optionList[optionTop].col;
steps[curStep].stepCnt = optionList[optionTop].stepCnt;
steps[curStep].direction = optionList[optionTop].direction;
steps[curStep].nextStep = -1;
pathHeadLength++;
row = steps[curStep].row;
col = steps[curStep].col;
if (board[row][col] == NOTOWER)
pathHeadTogo++;
visited[row][col] = true;
if ((steps[curStep].col == MAXCOLS - 2)
|| (pathHeadTogo > minTogo)
|| (pathHeadTogo > minSteps[row][col]))
{ if ( (steps[curStep].col == MAXCOLS - 2)
&& (pathHeadTogo <= minTogo))
{ /* savePath(); */
if (pathHeadTogo < minTogo) /* replace current shortest path(s) */
{ deleteRedPathList();
targ = 0;
redPathListTop = 1;
minTogo = pathHeadTogo;
}
else /* path HeadTogo = minTogo */
{ if (redPathListTop < MAXPATHLIST) /* add to list of shortest path(s) */
{ targ = redPathListTop++;
maxPathList = Math.max(redPathListTop, maxPathList);
}
else
targ = MAXPATHLIST;
}
if (targ == MAXPATHLIST)
{ if (debug)
statusMsg.setText("Out of space for Red PathList");
else
turnMsg.setText("");
}
else
{ cp = newStep();
redPathList[targ].length = pathHeadLength;
redPathList[targ].togo = pathHeadTogo;
redPathList[targ].firstStep = cp;
steps[cp].row = steps[pathHead].row;
steps[cp].col = steps[pathHead].col;
steps[cp].stepCnt = steps[pathHead].stepCnt;
steps[cp].direction = steps[pathHead].direction;
ph = steps[pathHead].nextStep;
lp = cp;
while (ph != -1)
{ cp = newStep();
steps[lp].nextStep = cp;
steps[cp].prevStep = lp;
steps[cp].row = steps[ph].row;
steps[cp].col = steps[ph].col;
steps[cp].stepCnt = steps[ph].stepCnt;
steps[cp].direction = steps[ph].direction;
ph = steps[ph].nextStep;
lp = cp;
}
steps[lp].nextStep = -1;
/* Be sure pointers are left in right state for recursion */
} }
/* else bailout */
}
else /* keep going */
{ minSteps[row][col] = pathHeadTogo;
switch (steps[curStep].direction) /* ROW1, COL1 is location of initial RedTOWER */
{ case UP:
row1 = steps[curStep].row - 1;
col1 = steps[curStep].col;
break;
case DOWN:
row1 = steps[curStep].row + 1;
col1 = steps[curStep].col;
break;
case LEFT:
row1 = steps[curStep].row;
col1 = steps[curStep].col-1;
break;
case RIGHT:
row1 = steps[curStep].row;
col1 = steps[curStep].col+1;
break;
}
stepCnt = steps[curStep].stepCnt + 1;
/* check LEFT */
considerRedMove(stepCnt, row1, col1-1, LEFT);
/* check UP */
considerRedMove(stepCnt, row1-1, col1, UP);
/* check DOWN */
considerRedMove(stepCnt, row1+1, col1, DOWN);
/* check right */
considerRedMove(stepCnt, row1, col1+1, RIGHT);
}
lastStep = curStep;
// if (pathCnt++ < 20)
// displayPath(pathHead, pathHeadLength, pathHeadTogo);
} /* End While (optionTop > 0) */
while (lastStep != -1)
{ row = steps[lastStep].row;
col = steps[lastStep].col;
visited[row][col] = false;
lp = steps[lastStep].prevStep;
deleteStep(lastStep);
lastStep = lp;
}
} /* end if board[1][c] != BLUETOWER */
} /* End for r = 1 to MAXROWS */
}
public static void deleteRedPathList()
{ int p, lp, cp;
for (p = 0; p < redPathListTop; p++)
{ cp = redPathList[p].firstStep;
while (cp != -1)
{ lp = cp;
cp = steps[cp].nextStep;
deleteStep(lp);
}
}
redPathListTop = 0;
}
public static void considerRedMove(int stepCnt, int row2, int col2, int direction)
{
if ((consider[row2][col2])
&& (!visited[row2][col2])
&& (board[row2][col2] != BLUETOWER) )
{ optionList[optionTop].stepCnt = stepCnt;
optionList[optionTop].row = row2;
optionList[optionTop].col = col2;
optionList[optionTop].direction = direction;
optionTop++;
maxOptions = Math.max(optionTop, maxOptions);
}
}
// public static void main(String args[]) {
// Bridges bridgeApp = null;
// bridgeApp = new Bridges("Bridge Application");
// bridgeApp.resize(MAXSCREENX, MAXSCREENY+75);
// bridgeApp.show(true);
// }
}