282 lines
9.8 KiB
XML
Executable File
282 lines
9.8 KiB
XML
Executable File
////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// 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
|