//////////////////////////////////////////////////////////////////// // // // SCRIPT NAME : Darts_AI.sch // // AUTHOR : Lino Manansala // // DESCRIPTION : AI Dart Throws // // // ////////////////////////////////////////////////////////////// USING "Darts_Dart_lib.sch" USING "Darts_Board.sch" ENUM DARTS_DIFFICULTY DARTSDIFF_NORMAL = 0, DARTSDIFF_HARD, DARTSDIFF_VERY_HARD ENDENUM STRUCT DARTS_AI_BRAIN INT iThrowValue INT iThrowMultiplier INT iScoreDifference INT iThrowTotal DARTS_DIFFICULTY eDifficulty ENDSTRUCT FUNC INT GET_ACCURACY_LOWER_LIMIT(DARTS_AI_BRAIN & DartsAIBrain) SWITCH DartsAIBrain.eDifficulty CASE DARTSDIFF_NORMAL RETURN 25 CASE DARTSDIFF_HARD RETURN 75 CASE DARTSDIFF_VERY_HARD RETURN 90 DEFAULT RETURN 25 ENDSWITCH ENDFUNC PROC GET_NEXT_AI_THROW(INT & iScore[], DARTS_AI_BRAIN & DartsAIBrain) //INT & DartsAIBrain.iThrowValue, INT & DartsAIBrain.iThrowMultiplier) INT i DartsAIBrain.iThrowValue = 0 DartsAIBrain.iThrowMultiplier = 0 DartsAIBrain.iScoreDifference = iScore[1] - iScore[0] DartsAIBrain.iThrowTotal++ // Still got a big score... so just go for those treble 20s! IF iScore[iPlayr] > 121//110 DartsAIBrain.iThrowValue = 20 DartsAIBrain.iThrowMultiplier = 3 ELIF iScore[iPlayr] > 60 // Now we're getting low, go for the treble 19 to cancel out our remainder IF iScore[iPlayr] % 2 = 1 IF GET_RANDOM_BOOL() DartsAIBrain.iThrowValue = 19 ELSE DartsAIBrain.iThrowValue = 17 ENDIF DartsAIBrain.iThrowMultiplier = 3 ELSE DartsAIBrain.iThrowValue = 20 DartsAIBrain.iThrowMultiplier = 3 ENDIF ELIF iScore[iPlayr] < 61 // we can checkout on the bull, go for this for style... it won't happen often IF iScore[iPlayr] = 50 DartsAIBrain.iThrowValue = 50 DartsAIBrain.iThrowMultiplier = 1 // hit a single to take our score down to 40, // then checkout on double 20 ELIF iScore[iPlayr] > 52 DartsAIBrain.iThrowValue = iScore[iPlayr] - 40 DartsAIBrain.iThrowMultiplier = 1 // hit a single to take our score down to 32, // then checkout on double 16 ELIF iScore[iPlayr] > 40 DartsAIBrain.iThrowValue = iScore[iPlayr] - 32 DartsAIBrain.iThrowMultiplier = 1 // our score is 40 or less ELSE // check to see if we can checkout on 1 dart... // if score is even, check us out IF iScore[iPlayr] % 2 = 0 i=1 REPEAT 20 i DartsAIBrain.iThrowValue = iScore[iPlayr] / 2 DartsAIBrain.iThrowMultiplier = 2 ENDREPEAT // we weren't able to 1 dart checkout, we've got an odd number ELSE // find the best 2 dart checkout from double 16 down to double 1 i = 32 WHILE DartsAIBrain.iThrowValue = 0 AND i > 1 IF iScore[iPlayr] > i DartsAIBrain.iThrowValue = iScore[iPlayr] - i DartsAIBrain.iThrowMultiplier = 1 ENDIF i /= 2 ENDWHILE ENDIF ENDIF ENDIF CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW] Pre-vector, DartsAIBrain.iThrowValue = ", DartsAIBrain.iThrowValue) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW] Pre-vector, DartsAIBrain.iThrowMultiplier = ", DartsAIBrain.iThrowMultiplier) ENDPROC PROC GET_AI_THROW_VECTOR(DART & Darts, DARTS_BOARD & DartsBoard, DARTS_PLAYER_STATE & turnStage, DARTS_AI_BRAIN & DartsAIBrain, BOOL bIsTutorial = FALSE) FLOAT fTempAI FLOAT fTemp1, fTemp2 FLOAT fAIThrowLength FLOAT fAIThrowAngle INT i INT iOpponentShotAccuracy VECTOR vTemp2, vTemp3 // Find out if the dart has landed in the bull, outer bull or out of the score zone IF DartsAIBrain.iThrowValue = 50 // bull fAIThrowLength = 0.0 fAIThrowAngle = GET_RANDOM_FLOAT_IN_RANGE(0.0, 360.0) ELIF DartsAIBrain.iThrowValue = 25 // outer bull fAIThrowLength = 0.14 fAIThrowAngle = GET_RANDOM_FLOAT_IN_RANGE(0.0, 360.0) // The dart is being aimed at a number ELSE // Set the length of the vector (treble, double, single) IF DartsAIBrain.iThrowMultiplier = 3 fAIThrowLength = 0.1345 // fAIThrowLength = 0.131 ELIF DartsAIBrain.iThrowMultiplier = 2 fAIThrowLength = 0.218 // fAIThrowLength = 0.208 ELSE fAIThrowLength = 0.180 ENDIF // Set the angle of the vector (the number it's aimed at) FLOAT fDartAngleIncremented =0.0 i=0 REPEAT 21 i IF DartsAIBrain.iThrowValue = iScoreForSection[i] fAIThrowAngle = fDartAngleIncremented ENDIF fDartAngleIncremented += 18.0 ENDREPEAT ENDIF IF NOT bIsTutorial AND DartsAIbrain.iThrowTotal < 30 // TODO: ADJUST DIFFICULTY HERE. FACTOR IN FRIEND ACTIVITY, AND PLAYER'S WINNING PCT // ************************************************************ // ******* Add randomness to the AI throw ********************* // ************************************************************ // ************************************************ ANGLE ***** i = GET_RANDOM_INT_IN_RANGE(0, 100) iOpponentShotAccuracy = GET_RANDOM_INT_IN_RANGE(GET_ACCURACY_LOWER_LIMIT(DartsAIBrain), 150) IF DartsAIBrain.iScoreDifference > 140 //Do a good shot if AI is way behind ftempAI = GET_RANDOM_FLOAT_IN_RANGE(-35.0, 35.0) //(-50.0, 50.0) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS IN COMEBACK MODE") ELIF i < iOpponentShotAccuracy AND DartsAIBrain.eDifficulty = DARTSDIFF_VERY_HARD fTempAI = GET_RANDOM_FLOAT_IN_RANGE(-80.0, 80.0) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS MAKING A VERY GOOD SHOT") ELIF i < iOpponentShotAccuracy AND DartsAIBrain.iScoreDifference > -140 // Do a good shot! while computer is not too far ahead fTempAI = GET_RANDOM_FLOAT_IN_RANGE(-60.0, 60.0) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS MAKING A GOOD SHOT") ELSE // Do a bad shot! fTempAI = GET_RANDOM_FLOAT_IN_RANGE(-100.0, 100.0) // Go left... IF fTempAI > 0 fTempAI = GET_RANDOM_FLOAT_IN_RANGE(-200.0, -60.0) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS MAKING A BAD SHOT LEFT") // Go right... ELSE fTempAI = GET_RANDOM_FLOAT_IN_RANGE(60.0, 200.0) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS MAKING A BAD SHOT RIGHT") ENDIF ENDIF fTempAI /= 10 fAIThrowAngle += fTempAI // ************************************************ LENGTH ***** i = GET_RANDOM_INT_IN_RANGE(0, 100) iOpponentShotAccuracy = GET_RANDOM_INT_IN_RANGE(GET_ACCURACY_LOWER_LIMIT(DartsAIBrain), 150) IF DartsAIBrain.iScoreDifference > 140 //Do a good shot if AI is way behind ftempAI = GET_RANDOM_FLOAT_IN_RANGE(-0.25, 0.25) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS IN COMEBACK MODE") ELIF i < iOpponentShotAccuracy AND DartsAIBrain.eDifficulty = DARTSDIFF_VERY_HARD fTempAI = GET_RANDOM_FLOAT_IN_RANGE(-0.07, 0.07) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS MAKING A VERY GOOD SHOT") ELIF i < iOpponentShotAccuracy AND DartsAIBrain.iScoreDifference > -140 // Do a good shot! while computer is not too far ahead fTempAI = GET_RANDOM_FLOAT_IN_RANGE(-0.15, 0.15) //(-0.3, 0.3) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS MAKING A GOOD SHOT") ELSE // Do a bad shot! fTempAI = GET_RANDOM_FLOAT_IN_RANGE(-100.0, 100.0) // Go high... IF fTempAI > 0 fTempAI = GET_RANDOM_FLOAT_IN_RANGE(-1.0, -0.3) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS MAKING A BAD SHOT HIGH") // Go low... ELSE fTempAI = GET_RANDOM_FLOAT_IN_RANGE(0.3, 1.0) CDEBUG1LN(DEBUG_DARTS, "[GET_NEXT_AI_THROW]********************* AI IS MAKING A BAD SHOT LOW") ENDIF ENDIF fTempAI /= 10 fAIThrowLength += fTempAI // ************************************************************ // ********************************************************** ENDIF // offset to the proper center of the board Darts.vTarget.x = SIN(fAIThrowAngle) * fAIThrowLength Darts.vTarget.y = -0.23 Darts.vTarget.z = COS(fAIThrowAngle) * fAIThrowLength Darts.vTarget.x -= 0.0035 Darts.vTarget.z -= 0.0002 IF turnStage = DPS_SKIP_AI CDEBUG1LN(DEBUG_DARTS, "*******************************") CDEBUG1LN(DEBUG_DARTS, "*AI Throw Length = ", fAIThrowLength) CDEBUG1LN(DEBUG_DARTS, "*Darts vTarget = ", Darts.vTarget) SET_DART_THROW_VECTOR(Darts) CDEBUG1LN(DEBUG_DARTS, "*Darts vOffsetTarget = ", Darts.vOffsetTarget) CDEBUG1LN(DEBUG_DARTS, "*******************************") ELSE Darts.bStuck = FALSE Darts.bTravelling = TRUE SET_DART_THROW_VECTOR(Darts) // create the dart Darts.object = CREATE_OBJECT(Darts.modelDart, vInitDartPos, FALSE, FALSE) fTemp1 = GET_RANDOM_FLOAT_IN_RANGE(0.0, 90.0) vTemp2 = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(DartsBoard.vDartBoard, DartsBoard.fBoardHeading, vInitDartPosOffset) vTemp3 = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(DartsBoard.vDartBoard, DartsBoard.fBoardHeading, << Darts.vTarget.x, Darts.vTarget.y + fdartboardOriginOffset, Darts.vTarget.z >>) fTemp2 = GET_HEADING_FROM_VECTOR_2D((vTemp2.x - vTemp3.x), (vTemp2.y - vTemp3.y)) fTemp2 -= 180 Darts.vRotation = << 90, fTemp1, fTemp2>> SET_ENTITY_ROTATION(Darts.object, Darts.vRotation, EULER_XYZ) Darts.vPosition = vInitDartPosOffset // keep track of the dart's offset turnStage = DPS_THROW PLAY_SOUND_FROM_ENTITY(-1, "DARTS_THROW_DART_MASTER", Darts.object) ENDIF ENDPROC