Fielding AI Logic

The logic the CPU players use when fielding is in the process of being decoded.

# Known AI Manipulations

* **Delayed double steal**: with any number of outs and the bases loaded, or with runners on 1B and 3B, steal with the 1B runner only before the pitch. After the pitch crosses the plate, press Y to send the other runners. This should cause the catcher to initially throw the ball to 2B, but then the 2B fielder will immediately throw home to try to get the runner advancing. If done correctly, the runner from 3B should score, and the other runners should have advanced 1 base.
* **Fake squeeze bunt**: With less than 2 outs and runners either on 1B and 3B, or 2B and 3B, bunt the ball. The fielder usually tries to throw home to get that runner. Just before the ball is thrown, send the runners back. This will allow the batter to reach first safely, and the other runners to remain on base. Additionally for the runners on 1st and 3rd situation, the strategy usually steals with the runner from 1B so the AI doesn't try a double play.
	+ Combining the above two strategies allows for a reliable way to continuously score runs. Examples can be found in this clip. https://www.twitch.tv/videos/1709324589

# AI Logic

## How the game decides the best strategy for each runner

What is known so far is how the game decides its strategy for dealing with each runner. The logic is laid out in the flowchart below. The strategy isn't necessarily used on each frame, since there is other logic that decides which runner to prioritize first, or if the fielder should do another action (such as throwing to the cutoff).

Some diagrams are given to visualize some of the situations, but most are not since those situations are too complicated to depict with a simple diagram.

## How the AI Decides Where to Throw the ball

The following logic will detail which runner the fielder will try to make a play on, based on the situation. The explanation goes into the main ideas of each situation, and glosses over a few details that are overly complicated, or aren't fully understood, so there might be some slight nuances when playing the actual game.

**"Desperation level"**: There's a 0-9 score that is not well understood that the game assigns to each runner, but it is used a lot in the fielder logic. The score seems to indicate something along the lines of "the desperation level needed to make the fielder want to make a play on that runner". If the level is high, that means there's little chance the chosen play will get the runner out, so the fielder needs to be really desperate to try the play anyways. If the level is low, then there's a high chance the chosen play will get the runner out.

**"Urgency level"**: The game classifies three situations as "urgent" based on the score and the inning.

* Level 3: If the score is tied in the bottom of the last inning
* Level 2: If the score is within 1 run in the last inning
* Level 1: If the game is in its last 4 innings, and the score is between winning by 1, or losing by 3.
* Level 0: any other situation.

**"R#"**: This article uses the shortform R# to refer to a runner coming from base number #. If it's the batter, it will be RB. For example, the runner coming from 1st base is R1.

## Initialization step

The game does a few preliminary checks at the start of the algorithm. Explanation to come.

## Balls in the Outfield

The following situations apply when the ball is in the deep outfield or if the ball is with an outfielder in the mid-outfield, and the fielder holding the ball isn't the cut-off character. The game will check if the following situations apply, in order:

1. If there are runners tagging up, and if a play can be made on them.
2. If runners can be thrown out from the outfield based on desperation level.
3. If the ball should be thrown home based on the runner's positions.
4. If none of the above apply, the throw is set to be to the cutoff, and then the game jumps to the final checks.

### Runners tagging up

On a fly ball catch, the game checks each fielder that is running back to their bag to tag-up. If there's a base within 45m and the desperation level is less than 5, then throw to that base (if there are multiple runners in this situation, throw to the closest).

### Outfield plays based on desperation level

#### Check 1: If there is a runner between 3B and home

* Throw home if the ball was caught, the runner from 3B has tagged up, the bases are loaded (could be wrong), and the fielder is between 62m and 0.35\*throwing power + 69m (the ranges for each throwing strength from 30-100 are shown in the screenshot).
* Otherwise, if there's a runner between 3B and home:
	+ If it's urgency level 2 or 3, throw home if the ball is within 75m from home, and the desperation level is less than 8 for urgency level 3, or less than 7 for urgency level 2.
	+ Otherwise, if the ball is within 68m of home, there's no other runners, and the desperation level on that runner is less than 5, then throw home.
* If neither of the above are applicable, then try check 2

#### Check 2: If there's a runner between 2B and 3B, the ball is within 62m of 3B, and the runner is running forwards.

* If there's also a runner between 1B and 2B, then if that runner is turning around, and the desperation level on the runner going to 3B is less than 5, then throw to 3rd.
* If not, then if the desperation level on the runner going to 3B is less than 6, then throw to 3rd.
* If neither apply, then try check 3

#### Check 3: If there is a runner between 1B and 2B

If this runner is going forward, the ball is within 50m of 2B, the desperation level is less than 6, and there's no other runner going home, then throw to 2B.

### Play at home plate based on the position of the runners

The following checks happen to see if the ball should be thrown to home plate if there is a runner going forwards that is within 15% before or after 3B

* If there's no runner who started at 1B, then throw home.
* If the runner from 1B doesn't need to tag up still and is already within 30% of 2B, then throw home.
* If the runner is tagging up, but is within 50% of 1B already, then throw home.

### No situations apply

The game will set the throw location to be the cutoff fielder. It will then jump to the final checks section to see if there are any overrides that apply.

## If there are 2 outs

This section is complicated in the code, so it will be completed later.

One point to note is that even if there are 2 outs, the algorithm has situations that don't terminate here and continue on to the next step.

## If the only runner is the batter going to 1B

*Recap: The ball isn't in the deep-ish outfield, there is less than 2 outs, or there are 2 outs but no play was set in the last step.*

If the desperation is less than 7, then try to get the batter-runner out. Otherwise, continue to the next step.

## If urgency level is 2 or 3

If the runner from 3B hasn't scored, or if any runner is in the 3B-home baseline who is running forward that's more than 20% towards home, then throw home. If urgency = 2, then this only applies with desperation level 7 or less.

Otherwise, continue to next step.

## If there's just 1 runner (non-RB)

If this runner is between 2B and home, then make a play on them if desperation is less than 7. Otherwise, if this runner is between 1B and 2B, then make a play on them if desperation is less than 6, and if something else about the runner is false.

## If the batter is running to 1B and other runners are present

There are several special situations that the game checks for when the batter is running to 1B.

*Recap: These situations apply if the ball isn't in the deep-ish outfield, there are less than 2 outs (with some exceptions), and there isn't an urgent situation to throw home.*

### If the bases are loaded

* If the ball is within the baselines and desperation level on the runner going home is less than 5 (or 4 if the urgency level is 0), then make a play home.
* Otherwise, if the urgency is 0 or 1, and the ball is within 5m of 3B, and the desperation level on the runner coming from 2B is less than 3, then make a play on the runner coming from 2B.
* Otherwise, if the ball is closer to 2B than it is to home. If the desperation on the runner from 1st or the runner from 3rd is less than 5, then try to get the relevant runner out. The prioritized runner depends on if the ball is closer to 2B or home. Otherwise, move on to the next step.

If none of the above apply, continue to the next step.

### Double play or prevent run? (specifically RB, R1, R3)

This is a specific situation for 3 runners (so a bases loaded scenario doesn't apply, even if a play wasn't decided in the last step).

* If there's a chance for a double play, then try it.
* Otherwise, if the ball is closer to 2B than home and the desperation level on the runner from 1B is less than 5, then throw to 2B.
* Otherwise, if the runner from 3B isn't moving forward, and desperation on that runner is less than 4, then try to get them out.
* If the ball is closer to home than 2B, then continue. Otherwise, go to next major step,
* If the runner from 3rd isn't turning around (I think), or the desperation level on them is less than 5, then throw to 2B if desperation on the runner from 1B is less than 5. Otherwise, go to next major step.
* If runner from 3rd is turning around (?) and desperation on them is less than 5:
	+ If there's no one covering 3rd, and desperation on R1 less than 4, then set play on R1.
	+ Otherwise, if there's a play on R3, then set play on R3.
* Otherwise, if desperation on R1 less than 5, then set play on R1.

If none of the above, move on to the next step.

### Double play chance (either RB and R1, or RB, R1, and R2)

* If there is an R2, and the ball is within 5m of 3B, and desperation on R2 is less than 3, then set play on R2 (basically a triple play attempt)
* Otherwise, if a double play on R1 and RB is possible, then set play on R1.
* Otherwise, if desperation level on R1 is more than 4, or there has yet to be an out on the play, then go to next major step.
* Otherwise, if the ball is within 2.5m of 1B and not desperate to get R1 out, then set play on RB.
* Otherwise, if there's a play to be made on R1, then set play to R1.

Else, go to next step.

### No force at 2B (RB and R3, or RB, R2, and R3)

If R3 is still within 25% of 3B, then move on to the next major step.

Otherwise:

* If the desperation on R3 is less than 4, then set the play on R3.
* Otherwise, if R3 is turning around, the desperation is less than 5, there's a fielder covering 3B, and (the runner is more then 50% towards home/ball is in 3B-home baseline), then set play on R3.

### Try to get lead runner at 3B without force (RB and R2)

* If R2 is around a quarter of the way towards 3B, and ball is in the infield on the 2B side of the second baseman, and desperation on R2 is less than 3 while on RB it's less than 4. Set play on R2.
* Otherwise, if ball is on the left side of the infield, the desperation on R2 is less than 5, there hasn't been an out on the play already, and R2 is more than 20% towards 3B, then set play on R2.
* Otherwise, move on to the next step.

### If there's a RB and no specific situation above triggered a play

If something < 2 and desperation on RB is less than 7, then set play to RB.

If something >= 2, and desperation on RB is less than 5, then set play on RB.

Otherwise, continue.

## If the ball was caught and runners are still tagging up

If there are runner's who can be put out while they are trying to tag-up, then try to throw them out if their desperation level is less than 5. The fielder will prioritize the closest base to throw to.

## Remaining situations where a runner is off of their base

The game will check the following for any runner off of their base. If there are multiple, it will prioritize R3, then R2, then R1.

* If the runner is more than 20% towards the next base with any movement type.
* If the runner is more than 15% towards the next base and running forward.
* If the runner isn't standing on a base, but the fielder is on the base behind them.

If none of the situations above apply, then move on to the next major step. If a situation does apply, then set the play to target the runner in question.

There is a fairly complicated final step to this, but it mainly boils down to if the ball is near the exact opposite base to where the play is, there's a chance that the play is overridden and player throws to the pitcher cutoff instead. Either way, jump to the final checks.

## Desperate play on batter-runner

If none of the above situations apply, then up the desperation level on the batter-runner to under 7 to make a play.

## Desperate play on runner going home

If there's a runner going home that isn't the batter, they aren't tagging up, and the desperation on them is under 7, then make a play on them, as long as there's no other runners in the middle of their baselines (15% away from each base).

## Anything leftover

If there's runners moving that don't fit any of the situations above, then target them. If not, then target any runner that's not on a base.

## Final checks to override the throw location

At the end of the algorithm, there are several cases that override the calculated throw location from above that could cancel the throws.

* If the fielder covering the base that's about to be thrown to is on fire, knocked out, or body checked, then cancel the throw.
* If ground ball with less than 2 outs, and desperation on batter is really low, then if there's an R2 or R3 that has just left their bag, then don't throw (I guess this is pausing to see if a better play can be made on a lead runner)
* Something about a high CPU difficulty, and low desperation on batter, but something else always seems to be false, so this might never happen.
* If throwing to the cutoff, don't throw if one doesn't exist, the current fielder is the cutoff, the current fielder is closer to the infield than the cutoff, or the cutoff throw would be less than 5m.

### Make running play instead

At the very end of the whole algorithm, the game checks if the fielder should make a running play instead.

If there is a running strat available, and (there's been either 0 or 2+ throws during the play, or it's been more than 45 frames since the last throw, or something else = 0), then cancel the throw and do the running play on the runner.