#include #include #include #include #include "9ball.h" #include "interface.h" #include "physics.h" #include "utility.h" #include "team.h" #include "player.h" #include "global.h" const unsigned int BILLIARDS_COUNT = 15; K_EXPORT_COMPONENT_FACTORY( libkue9ball, NineBallFactory ) TQObject *NineBallFactory::createObject (TQObject *parent, const char* name, const char* classname, const TQStringList &args = TQStringList() ) { Q_UNUSED(args); if (classname != TQString("KueRulesEngine")) return 0; return new NineBall(parent, name); } NineBall::NineBall(TQObject *parent, const char *name) : KueRulesEngine(parent, name) { KueUtility::layoutTable(); KueUtility::layoutPockets(); KueUtility::layoutBilliards(KueUtility::Diamond); // Reset our state (NOTE: anyone see anything missing?) _current_team = 0; _first_hit = -1; _first_sunk = -1; _foul = false; _broke = false; _current_player = KueGlobal::teams()->at(_current_team)->nextPlayer(); } NineBall::~NineBall() { } void NineBall::start() { cuePlaced(); } void NineBall::billiardSunk(unsigned int ball, unsigned int pocket) { Q_UNUSED(pocket); // Ah, it's all good... if (_first_sunk == -1) _first_sunk = ball; if (ball == 0) _foul = true; } void NineBall::billiardHit(unsigned int ball1, unsigned int ball2) { // Is this our first hit? if (_first_hit == -1) { // Select the ball involved which isn't the cue ball _first_hit = ball1 ? ball1 : ball2; if (!ballIsLowest(_first_hit)) _foul = true; _broke = true; } } void NineBall::motionStopped() { // The physics engine has finished its job, turn it off to save CPU time KueGlobal::physics()->stop(); // Are all the balls 1-9 gone? if (ballIsLowest(10)) { playerWins(); return; } // We lose our turn if the shot was a scratch, or we sunk nothing if ((_foul) || (_first_sunk == -1)) { if (_current_team == 0) _current_team = 1; else _current_team = 0; _current_player = KueGlobal::teams()->at(_current_team)->nextPlayer(); } // Reset our shot state _first_hit = -1; _first_sunk = -1; // Did we scratch? if (_foul) { // Recreate the cue call KueBilliard cue( KueGlobal::physics()->fieldWidth() / 4.0, KueGlobal::physics()->fieldHeight() / 2.0, KueUtility::defaultBilliardRadius() ); if (_broke) { // Ask the user where to place the billiard emit(showMessage(placeCueBallMessage())); _current_player->placeBilliard( 0, cue, KueGlobal::physics()->fieldWidth() / 4.0, this, TQ_SLOT(cuePlaced()) ); } else { // We scratched, the cue ball goes back home KueGlobal::physics()->insertBilliard(0, cue); cuePlaced(); } } else { emit(showMessage(startShotMessage())); // The cue ball stays where it is, go right to the shot _current_player->takeShot(0, false, this, TQ_SLOT(shotTaken())); } } // Is a ball 'magic' (8 ball)? bool NineBall::ballIsLowest(unsigned int number) { for (unsigned int x = 1;x < number;x++) if (KueGlobal::physics()->billiards()[x]) return false; return true; } // Is a ball the cue ball (ball 0) bool NineBall::ballIsCue(unsigned int number) { return (number == 0); } void NineBall::playerWins() { TQString message; // Announce the winner message = i18n("%1 wins!").arg(_current_player->name()); // Show the message emit(showMessage(message)); // Tell the rest of the game about the stunning victory emit(gameOver(message)); } TQString NineBall::startShotMessage() { TQString message; // What type of shot is this? if (_broke) message = i18n("%1's shot").arg(_current_player->name()); else message = i18n("%1's break shot").arg(_current_player->name()); return message; } TQString NineBall::placeCueBallMessage() { TQString message; // Tell the user what is going on message = i18n("%1 placing cue ball").arg(_current_player->name()); return message; } void NineBall::cuePlaced() { // Tell the interface code to start the shot emit(showMessage(startShotMessage())); _current_player->takeShot(0, true, this, TQ_SLOT(shotTaken())); } void NineBall::shotTaken() { // Start the physics engine KueGlobal::physics()->start(); // Reset the shot-related variables _foul = false; _first_hit = -1; _first_sunk = -1; } #include "9ball.moc"