The following occurred to someone in the Discord, and after poring through the source code, I've figured out what occurred.
4th and 3. The offense scores a passing touchdown.
The QB drops back (recording a dropback PlayEvent).
This calls state.incrementDown(). state.down is now 5.
He throws a passing touchdown (recording a pssTD PlayEvent).
state.awaitingAfterTouchdown is set to true.
state.scrimmage is now in the endzone.
After the play, this.currentPlay.commit() is called.
checkDownAtEndOfPlay sees that state.scrimmage is in the endzone, and returns without checking the down.
There are no penalties to adjudicate.
The play's ending state is committed to the GameSim object. The down of the GameSim object is now 5.
The offense lines up for the extra point, and gets called for Unsportsmanlike Conduct.
getPlayType determines the offense should kick the extra point (return "extraPoint";)
simPlay calls doFieldGoal as a result.
doFieldGoal, which handles the extra point, calls checkPenalties("beforeSnap") to see if there are any pre-snap penalties.
checkPenalties, after random chance, decides that an offensive player committed Unsportsmanlike Conduct.
This carries a 15 yard penalty from the previous spot.
This penalty is logged on the currentPlay object.
The currentPlay object dutifully subtracts the 15 yards from state.scrimmage, removing it from the endzone (which is 10 yards at most).
Because checkPenalties did, in fact, return a penalty, doFieldGoal returns early.
this.currentPlay.commit() is called.
As state.scrimmage is no longer in the endzone, checkDownAtEndOfPlay does not return early, and, seeing the down to be 5, from earlier, turns the ball over on downs.
We are still waiting after a touchdown, so the offense lines up for the extra point...
...except the offense and defense switched due to the errant turnover on downs!
The offense (originally the defense) attempts the extra point, since, as far as the game is concerned, they are the offense for this play.
In this case, they make it, although that doesn't matter for what happens next.
As they attempted the extra point, make or miss, they're kicking off next.
The team who gave up the touchdown is now kicking off to the team that just scored!
The solution, as far as I can tell, could be as simple as adding a check to checkDownAtEndOfPlay to return early if we're in an extra point try. (Or, extra points could be treated like two point conversions, where penalties are just ignored.)
TL;DR: Due to how the game handles downs and advancing them, a penalty on the extra point after a touchdown that is scored on a team's 4th down will cause the game to turn the ball over on downs, make the team that was just scored on kick the extra point, and then make them kick the ball to the team that just scored on them.
The following occurred to someone in the Discord, and after poring through the source code, I've figured out what occurred.
dropback
PlayEvent).state.incrementDown()
.state.down
is now 5.pssTD
PlayEvent).state.awaitingAfterTouchdown
is set totrue
.state.scrimmage
is now in the endzone.this.currentPlay.commit()
is called.checkDownAtEndOfPlay
sees thatstate.scrimmage
is in the endzone, and returns without checking the down.GameSim
object. The down of the GameSim object is now 5.getPlayType
determines the offense should kick the extra point (return "extraPoint";
)simPlay
callsdoFieldGoal
as a result.doFieldGoal
, which handles the extra point, callscheckPenalties("beforeSnap")
to see if there are any pre-snap penalties.checkPenalties
, after random chance, decides that an offensive player committed Unsportsmanlike Conduct.currentPlay
object.currentPlay
object dutifully subtracts the 15 yards fromstate.scrimmage
, removing it from the endzone (which is 10 yards at most).checkPenalties
did, in fact, return a penalty,doFieldGoal
returns early.this.currentPlay.commit()
is called.state.scrimmage
is no longer in the endzone,checkDownAtEndOfPlay
does not return early, and, seeing the down to be 5, from earlier, turns the ball over on downs.The solution, as far as I can tell, could be as simple as adding a check to
checkDownAtEndOfPlay
to return early if we're in an extra point try. (Or, extra points could be treated like two point conversions, where penalties are just ignored.)TL;DR: Due to how the game handles downs and advancing them, a penalty on the extra point after a touchdown that is scored on a team's 4th down will cause the game to turn the ball over on downs, make the team that was just scored on kick the extra point, and then make them kick the ball to the team that just scored on them.