Commit 1fffad2a authored by Terence Martin's avatar Terence Martin

Replace ball swapping with direct dropping

Originally, the MazeContent class would store an array that contained
the balls left to be played for both the human and computer player
along with a variable that indicated which of the two were currently
visible in the maze. We would then save the balls from the maze into
one array and restore from the other.

This actually causes a problem in that this gets the balls in the
array out of sync with reality if you don't swap right away.

For example, if the computer pushes a ball, then we check to see if
the human can play a ball and cannot (all blocked), then we check to
see if the computer can play to see if they can take another turn,
since we did not save the ball state and the check happens from the
array, it thinks it can play the ball it just played.

If that ball is the only ball that can be played, this gets us into
a situation where there is actually no move to be made.

Now we instead just restore from an array to the maze, and every time
a ball drops we check to see if it was in one of the arrays and remove
it from there, thus always keeping everything in sync.
parent bdde1e10
This diff is collapsed.
......@@ -51,12 +51,6 @@ module nurdz.game
*/
private _computerBalls : Array<Ball>;
/**
* The set of balls (human or computer player) that is currently
* visualized into the top row of the maze content area.
*/
private _visibleBallType : PlayerType;
/**
* This is an array the same size as the _contents array which contains
* a boolean that indicates if this position should be marked with a
......@@ -144,37 +138,6 @@ module nurdz.game
get computerBalls () : Array<Ball>
{ return this._computerBalls; }
/**
* We can only view the balls playable by the player or by the computer
* in the top row of the maze, not both at once. This indicates which
* one is currently being displayed.
*
* @returns {PlayerType} the player whose balls are currently visible.
*/
get visibleBallType () : PlayerType
{ return this._visibleBallType; }
/**
* Set the balls that are currently visible in the maze to the balls for
* the player type provided.
*
* This clobbers what is already in the top row of the maze with the
* new contents, so use this with care; if the balls in the top row are
* of a different type and have been manipulated, those manipulations
* will be lost.
*
* @param {PlayerType} newType the new player type.
*/
set visibleBallType (newType : PlayerType)
{
// Set the type and then force the provided balls to be visible.
this._visibleBallType = newType;
if (this._visibleBallType == PlayerType.PLAYER_HUMAN)
this.restoreFromBallArray (this._playerBalls);
else
this.restoreFromBallArray (this._computerBalls);
}
/**
* Construct a new maze content object. This will create the underlying
* data structure and initialize it to be completely devoid of cells
......@@ -197,10 +160,6 @@ module nurdz.game
this._position = new Point (0, 0);
this._cellSize = 0;
// Start out with the player balls originally visible.
this._visibleBallType = PlayerType.PLAYER_HUMAN;
// Start everything cleared out. This ensures that the arrays are
// properly initialized.
this.clearCells ();
......@@ -471,36 +430,6 @@ module nurdz.game
return this.playableBallsInArray (this._computerBalls);
}
/**
* Copy the balls from the first row of the maze into the ball array
* passed in. Any missing balls become a null entry in the ball array as
* well.
*
* During the save, every ball that is saved is marked as being hidden
* so that it will no longer visually appear on the screen.
*
* @param {Array<Ball>} ballArray the ball array to save into
*/
private saveToBallArray (ballArray : Array<Ball>) : void
{
// Search the top row of the maze contents and store what we find.
// The ball index in the array is the offset from the first column
// in the maze contents.
for (let ballIndex = 0 ; ballIndex < ballArray.length ; ballIndex++)
{
ballArray[ballIndex] = <Ball> this.getCellAt (ballIndex + 1, 0);
if (ballArray[ballIndex] != null)
{
// Just to be save, clear the cell before we hide this ball
// so that the update loop can't whack it. Pretty sure this
// can't happen but I never want to experience this bug
// again, sooo...
this.clearCellAt (ballIndex + 1, 0);
ballArray[ballIndex].hide ();
}
}
}
/**
* Copy the balls from the ball array provided into the first row of the
* maze. Any missing balls become a null entry in the maze contents.
......@@ -524,31 +453,72 @@ module nurdz.game
}
/**
* Swap the balls that are currently visible in the maze top row between
* the currently visible ones and the balls for the opposing player.
* Invoke the hide method for all balls currently in the array provided,
* removing them from the screen.
*
* In order to determine which player's balls are currently visible you
* can use the visibleBallType property.
* @param {Array<Ball>} ballArray the array of balls to hide
*/
private hideBallsInArray (ballArray : Array<Ball>) : void
{
// Iterate all balls in the provided array and hide them.
for (let ballIndex = 0; ballIndex < ballArray.length ; ballIndex++)
{
if (ballArray[ballIndex] != null)
ballArray[ballIndex].hide ();
}
}
/**
* Given a ball, this checks to see if this ball entity exists in either
* the list of unplayed player balls or unplayed computer balls. If the
* ball is found in one of those arrays, it is removed from the array so
* that the code knows that this ball has now been played.
*
* This will save the currently displayed balls in the top row before
* swapping in the opposing set.
* @param {Ball} ball the ball to remove
*/
swapVisibleBalls () : void
markBallPlayed (ball : Ball) : void
{
// Based on the visible ball type, save to one ball array and
// restore from the other.
if (this._visibleBallType == PlayerType.PLAYER_HUMAN)
let index = this._playerBalls.indexOf (ball);
if (index != -1)
{
this.saveToBallArray (this._playerBalls);
this.restoreFromBallArray (this._computerBalls);
this._visibleBallType = PlayerType.PLAYER_COMPUTER;
console.log("Marking a player ball as played");
this._playerBalls[index] = null;
return;
}
else
index = this._computerBalls.indexOf (ball)
if (index != -1)
{
this.saveToBallArray (this._computerBalls);
this.restoreFromBallArray (this._playerBalls);
this._visibleBallType = PlayerType.PLAYER_HUMAN;
console.log("Marking a computer ball as played");
this._computerBalls[index] = null;
return;
}
// Theoretically this can only happen when the debug code inserts a
// ball into the top row that the generator did not insert there.
console.log("Played a ball that is not in either of the two ball arrays");
}
/**
* Replace the top row contents of the maze with the list of balls that
* remain to be played for the player and simultaneously hide all of the
* computer balls still in the top row.
*/
showPlayerBalls () : void
{
this.restoreFromBallArray (this._playerBalls);
this.hideBallsInArray (this._computerBalls);
}
/**
* Replace the top row contents of the maze with the list of balls that
* remain to be played for the computer and simultaneously hide all of
* the player balls still in the top row.
*/
showComputerBalls () : void
{
this.restoreFromBallArray (this._computerBalls);
this.hideBallsInArray (this._playerBalls);
}
/**
......
......@@ -499,12 +499,6 @@ module nurdz.game
playerBalls[ballIndex].hide ();
computerBalls[ballIndex].hide ();
}
// Now set the visible ball type in the maze content back to its
// current value. This will force it to display the balls of the
// player that is currently set so that the swaps will work from
// here on out.
this._contents.visibleBallType = this._contents.visibleBallType;
}
/**
......
......@@ -545,6 +545,12 @@ module nurdz.game
*/
private dropBall (ball : Ball, speed : number) : void
{
// Get the maze contents to mark this ball as played. If this is
// one of the generated human or computer balls from the top row,
// this will remove it from the list of balls so that the code knows
// that this ball is no longer available.
this._contents.markBallPlayed (ball);
// Set the entity that is currently dropping to the one provided,
// then remove it from the maze. It will be re-added when
// it is finished moving
......
......@@ -362,14 +362,12 @@ module nurdz.game
// For debugging purposes, this key swaps to human balls
case KeyCodes.KEY_Z:
console.log ("human balls");
this._maze.contents.visibleBallType = PlayerType.PLAYER_HUMAN;
this._maze.contents.showPlayerBalls ();
return true;
// For debugging purposes, this key swaps to computer balls.
case KeyCodes.KEY_X:
console.log ("computer balls");
this._maze.contents.visibleBallType = PlayerType.PLAYER_COMPUTER;
this._maze.contents.showComputerBalls ();
return true;
}
......@@ -533,8 +531,7 @@ module nurdz.game
case GameState.PLAYER_TURN:
this._player.visible = true;
this._computer.visible = false;
if (this._maze.contents.visibleBallType != PlayerType.PLAYER_HUMAN)
this._maze.contents.swapVisibleBalls ();
this._maze.contents.showPlayerBalls ();
break;
// It is now the turn of the computer player, so make sure that
......@@ -542,8 +539,7 @@ module nurdz.game
case GameState.COMPUTER_TURN:
this._computer.visible = true;
this._player.visible = false;
if (this._maze.contents.visibleBallType != PlayerType.PLAYER_COMPUTER)
this._maze.contents.swapVisibleBalls ();
this._maze.contents.showComputerBalls ();
// Tell the computer that they're starting their turn now.
this._computer.ai_startingTurn ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment