/// <summary> /// Adds a roll to this frame. /// </summary> /// <param name="pinsKnockedDown"></param> public void AddRoll(Roll pinsKnockedDown) { if (pinsKnockedDown == null) { throw new ArgumentNullException("Roll cannot be null."); } if (firstRoll == null) { firstRoll = pinsKnockedDown; } else if (secondRoll == null) { secondRoll = pinsKnockedDown; } else if (FrameType == FrameOptions.FrameTypes.FINAL_FRAME) { thirdRoll = pinsKnockedDown; } else { throw new ArgumentOutOfRangeException("No more rolls allowed in this frame."); } }
/// <summary> /// Main Engine processor -- processes the roll and advances frames and game state. /// </summary> /// <param name="roll"></param> private void ProcessRoll(Roll roll) { PinsStanding -= roll.RollValue; switch (GameState) { //starting a new frame case GameStateOptions.State.NEW_FRAME: frames[currentIndex].AddRoll(roll); ProcessPendingStrikeFrames(roll); ProcessPendingSpareFrame(roll); if (roll.RollValue == Roll.MAX_SINGLE_ROLL) { //a strike strikeQueue.Enqueue(frames[currentIndex]); frames[currentIndex].InStrikeQueue = true; if (currentIndex == PENULTIMATE_FRAME_INDEX) { GameState = GameStateOptions.State.FINAL_FRAME; } else { GameState = GameStateOptions.State.NEW_FRAME; } currentIndex++; ResetPins(); } else { //no strike continue frame GameState = GameStateOptions.State.NEW_FRAME_SECOND_ROLL; } break; //second roll on the current frame case GameStateOptions.State.NEW_FRAME_SECOND_ROLL: frames[currentIndex].AddRoll(roll); ProcessPendingStrikeFrames(roll); ProcessPendingSpareFrame(roll); if (PinsStanding == 0) { //a spare spareFrame = frames[currentIndex]; spareFrame.InSpareQueue = true; } if (currentIndex == PENULTIMATE_FRAME_INDEX) { GameState = GameStateOptions.State.FINAL_FRAME; } else { //finished with this frame, start a new one GameState = GameStateOptions.State.NEW_FRAME; } ResetPins(); currentIndex++; break; //starting the final frame case GameStateOptions.State.FINAL_FRAME: frames[currentIndex].AddRoll(roll); ProcessPendingStrikeFrames(roll); ProcessPendingSpareFrame(roll); if (roll.RollValue == Roll.MAX_SINGLE_ROLL) { //a strike GameState = GameStateOptions.State.FINAL_FRAME_SECOND_ROLL_STRIKE; ResetPins(); } else { //no strike GameState = GameStateOptions.State.FINAL_FRAME_SECOND_ROLL; } break; //start the second roll if the first roll in this frame was not a strike case GameStateOptions.State.FINAL_FRAME_SECOND_ROLL: frames[currentIndex].AddRoll(roll); ProcessPendingStrikeFrames(roll); ProcessPendingSpareFrame(roll); if (PinsStanding == 0) { //a spare, so lets go to third roll GameState = GameStateOptions.State.FINAL_FRAME_THIRD_ROLL; ResetPins(); } else { GameState = GameStateOptions.State.END_GAME; currentIndex++; } break; //first roll of final frame was a strike case GameStateOptions.State.FINAL_FRAME_SECOND_ROLL_STRIKE: frames[currentIndex].AddRoll(roll); ProcessPendingStrikeFrames(roll); ProcessPendingSpareFrame(roll); GameState = GameStateOptions.State.FINAL_FRAME_THIRD_ROLL; break; //in the final frame, first roll was either a strike or the second roll was a spare case GameStateOptions.State.FINAL_FRAME_THIRD_ROLL: frames[currentIndex].AddRoll(roll); ProcessPendingStrikeFrames(roll); ProcessPendingSpareFrame(roll); GameState = GameStateOptions.State.END_GAME; currentIndex++; break; case GameStateOptions.State.END_GAME: default: break; } FinalizeFrames(); }
public void RecordRollResult(Roll roll) { this.Rolls.Add(roll); }