int Player::gainOrLoseLife(int value) { if (!value) return 0; //Don't do anything if there's no actual life change if (value>0 && (opponent()->game->battlefield->hasAbility(Constants::NOLIFEGAINOPPONENT)||game->battlefield->hasAbility(Constants::NOLIFEGAIN)))//nolifegain return 0; thatmuch = abs(value); //the value that much is a variable to be used with triggered abilities. //ie:when ever you gain life, draw that many cards. when used in a trigger draw:thatmuch, will return the value //that the triggered event stored in the card for "that much". if (!inPlay()->hasAbility(Constants::CANTCHANGELIFE)) life+=value; if (value<0) lifeLostThisTurn += abs(value); else if (value > 0) { lifeGainedThisTurn += abs(value); } //Send life event to listeners WEvent * lifed = NEW WEventLife(this,value); observer->receiveEvent(lifed); return value; }
void SuperBall::paddle_launch(Vector3D norm, Vector3D paddle_velocity) { if (!inPlay()) { _ball->launch(C_VELOCITY_REDUCE * (norm + paddle_velocity)); } }
int SuperBall::tick() { if (!inPlay()) return 1; Point3D to = _ball->getPosition(); m_transform = translation(Vector3D(to[0], to[1], to[2])); return 0; }
void AI::generateMoves(fizGTableState state, set<shot>& moves, turn_T turn){ //for each ball fizBall cueBall = state.getBall(CUE); //must have been a scratch, ball in hand...figure out what to do if(!inPlay(cueBall)) return; fizPoint cueBallPos = cueBall.getPos(); BallType firstBall, lastBall; switch(turn){ case stripes: firstBall = EIGHT; lastBall = FIFTEEN; break; case solids: firstBall = ONE; lastBall = EIGHT; break; case table_open: firstBall = ONE; lastBall = FIFTEEN; break; } for(BallType ballNum = firstBall; ballNum <= lastBall; ballNum = (BallType)(ballNum + 1)){ if(ballNum == EIGHT && !isOnly8Left(state, (turn == solids))) continue; fizBall ball = state.getBall(ballNum); //if ball is not in play if(!inPlay(ball)) continue; fizPoint ballPos = ball.getPos(); //for each pocket, generate a straight in shot int numOfPockets = 6; BoundaryId pockets[] = {SW_POCKET, W_POCKET, NW_POCKET, NE_POCKET, E_POCKET, SE_POCKET}; for(int i = 0; i < numOfPockets; i++){ //get ball position, cue ball position, and pocket position //calculate ghost ball position //calculate theta, a, b, phi, and minVelocity fizPoint pocketPos = theTable->getPocketCenter(pockets[i]); //make sure shot is possible //if(!shotPossible(cueBallPos, ballPos, pocketPos)) continue; //get ball-pocket line and cue-ghostball line double yDiff = fabs(pocketPos.y - ballPos.y); double xDiff = fabs(pocketPos.x - ballPos.x); double ballPocketAngle = atan( yDiff / xDiff); double deltaX = ballDiameter * cos(ballPocketAngle); double deltaY = ballDiameter * sin(ballPocketAngle); if(ballPos.x < pocketPos.x) deltaX = -deltaX; if(ballPos.y < pocketPos.y) deltaY = -deltaY; double ghostX = ballPos.x + deltaX; double ghostY = ballPos.y + deltaY; fizPoint ghostPos(ballPos.x + deltaX, ballPos.y + deltaY); //make sure no balls are in the way //this should also make sure that the shot is possible because //if it is not possible then the target ball will be in the way of the cue and ghost vec2 p1; p1.x = cueBallPos.x; p1.y = cueBallPos.y; vec2 p2; p2.x = ghostPos.x; p2.y = ghostPos.y; if(!isTrajectoryClear(p1, p2, state, -1)) continue; p1.x = ballPos.x; p1.y = ballPos.y; p2.x = pocketPos.x; p2.y = pocketPos.y; if(!isTrajectoryClear(p1, p2, state, -1)) continue; //ok create the shot //set a, b to zero //find minimum velocity //find cue angle and elevation angle shot theShot; theShot.a = 0; //positive is to right of center (mm) theShot.b = 0; //positive is up from center (mm) //theShot.v = 1; //have to calculate the minimum required velocity (m/s) max = 4.5 xDiff = fabs(cueBallPos.x - ghostPos.x); yDiff = fabs(cueBallPos.y - ghostPos.y); theShot.phi = atan(yDiff / xDiff); //convert to degrees theShot.phi *= (180.0 / M_PI); //find true angle if(cueBallPos.x < ghostPos.x){ if(cueBallPos.y > ghostPos.y){ theShot.phi = -theShot.phi; } else{ //have correct angle } } else{ if(cueBallPos.y < ghostPos.y){ theShot.phi = 180 - theShot.phi;//90 + theShot.phi; } else{ theShot.phi = 180 + theShot.phi; //180 + theShot.phi; } } //distance from ball to pocket theShot.d1 = pointDistance(ballPos, pocketPos); //distance from cue to ghost theShot.d2 = pointDistance(cueBallPos, ghostPos); //slopes of lines, to determine angles yDiff = ballPos.y - pocketPos.y; xDiff = ballPos.x - pocketPos.x; double yDiff2 = cueBallPos.y - ghostPos.y; double xDiff2 = cueBallPos.x - ghostPos.x; theShot.cutAngle = angleBetweenLines(yDiff, xDiff, yDiff2, xDiff2); //determine the pocket angle bool isCorner = true; switch(pockets[i]){ case W_POCKET: case E_POCKET: yDiff2 = 0; xDiff2 = 1; isCorner = false; break; case SW_POCKET: yDiff2 = 1; xDiff2 = 1; break; case NW_POCKET: yDiff2 = -1; xDiff2 = 1; break; case NE_POCKET: yDiff2 = -1; xDiff2 = -1; break; case SE_POCKET: yDiff2 = 1; xDiff2 = -1; break; } theShot.pocketAngle = angleBetweenLines(yDiff, xDiff, yDiff2, xDiff2); theShot.v = vTable.getMinVelocity(theShot.d2, theShot.d1, theShot.cutAngle) + .2; if(theShot.v < 0){ continue; } ShotData shotCopy; shotCopy.a = theShot.a; shotCopy.b = theShot.b; shotCopy.v = theShot.v; shotCopy.theta = 2; shotCopy.phi = theShot.phi; theShot.theta = findMinTheta(*theTable, state, shotCopy); //elevation angle (degrees) theShot.ball = ballNum; theShot.pocket = pockets[i]; theShot.probability = pTable.getProb(theShot.d1, theShot.d2, theShot.cutAngle, theShot.pocketAngle, isCorner); if(theShot.probability == 0) theShot.probability = .001; //add shot to the list moves.insert(theShot); } } }