Someone added a comment to my post on Bowling in C++ part 2 asking for the source code. Here it is.
template<bool value>
struct Assert
{
char assertion_failed[value];
};
template<unsigned lhs,unsigned rhs>
struct AssertEqual:
Assert<lhs==rhs>
{};
template<typename GameState>
struct IsLastFrame
{
static const bool value=GameState::frameCount==10;
};
template<typename GameState>
struct NextRollCounts
{
static const bool value=GameState::ballsLeftThisFrame ||
!IsLastFrame<GameState>::value;
};
template<typename GameState>
struct NextBallIsStartOfFrame
{
static const bool value=NextRollCounts<GameState>::value && !GameState::ballsLeftThisFrame;
};
struct NullGame
{
typedef NullGame PreviousGameState;
static const bool isStrike=false;
static const bool isSpare=false;
static const unsigned totalScore=0;
static const bool ballsLeftThisFrame=false;
static const unsigned frameCount=0;
static const unsigned roll=0;
};
template<typename GameState>
struct NextBallIsLastInFrame
{
static const bool value=GameState::ballsLeftThisFrame;
};
template<typename GameState>
struct BonusMultiplier
{
typedef typename GameState::PreviousGameState PreviousGameState;
static const unsigned value=(NextRollCounts<PreviousGameState>::value && (GameState::isStrike || GameState::isSpare)) + PreviousGameState::isStrike;
};
template<typename GameState>
struct RollMultiplier
{
static const unsigned value=BonusMultiplier<GameState>::value+NextRollCounts<GameState>::value;
};
template<typename GameState,unsigned roll_>
struct Roll
{
typedef GameState PreviousGameState;
static const unsigned roll=roll_;
static const bool isSpare=GameState::ballsLeftThisFrame && ((roll+GameState::roll)==10);
static const bool isStrike=NextBallIsStartOfFrame<GameState>::value && roll==10;
static const bool ballsLeftThisFrame=NextBallIsStartOfFrame<GameState>::value && !isStrike;
static const unsigned frameCount=GameState::frameCount+
NextBallIsStartOfFrame<GameState>::value;
static const unsigned totalScore=GameState::totalScore+
RollMultiplier<GameState>::value*roll;
};
AssertEqual<Roll<NullGame,0>::totalScore,0> roll0Scores0;
AssertEqual<Roll<NullGame,6>::totalScore,6> roll6Scores6;
AssertEqual<Roll<Roll<NullGame,6>,3>::totalScore,9> roll63Scores9;
AssertEqual<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<
NullGame,6>,3>,6>,3>,6>,3>,6>,3>,6>,3>,6>,3>,6>,3>,6>,3>,6>,3>,6>,3>::totalScore,90> allOpen;
AssertEqual<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<
NullGame,6>,4>,6>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>::totalScore,22> spare;
AssertEqual<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<
NullGame,4>,4>,2>,4>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>,0>::totalScore,14> notSpare;
AssertEqual<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<
NullGame,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>,5>::totalScore,150> allSpares;
AssertEqual<Roll<Roll<Roll<Roll<Roll<NullGame,10>,4>,5>,3>,0>::totalScore,31> strike;
AssertEqual<Roll<Roll<Roll<Roll<NullGame,10>,10>,4>,5>::totalScore,24+19+9> doubleStrike;
AssertEqual<Roll<Roll<Roll<Roll<Roll<NullGame,10>,10>,10>,4>,5>::totalScore,30+24+19+9> tripleStrike;
AssertEqual<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<
NullGame,10>,4>,6>,10>,4>,6>,10>,4>,6>,10>,4>,6>,10>,4>,6>,10>::totalScore,200> alternating;
typedef Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<Roll<
NullGame,10>,10>,10>,10>,10>,10>,10>,10>,10>,10>,10>,10> PerfectGame;
AssertEqual<PerfectGame::frameCount,10> perfectFrameCount;
AssertEqual<BonusMultiplier<PerfectGame::PreviousGameState>::value,1> perfectFrameFinalBonus;
Assert<!NextRollCounts<PerfectGame::PreviousGameState>::value> perfectFrameFinalBallCounts;
AssertEqual<PerfectGame::PreviousGameState::ballsLeftThisFrame,0> perfectFrameFinalBallsLeft;
AssertEqual<PerfectGame::totalScore,300> perfect;