Basketball game clock rewrite

The play-by-play in BBGM has always been a little weird. If you looked at it closely, you would notice some strange and unrealistic things related to the game clock. Today a bunch of that is fixed. Here's a list of some of the changes you might notice:

Although I did do some beta testing (join the ZenGM Discord server if you want to know about future betas), it's very likely that there is some new bug or some old simulation weirdness that I forgot about. If you notice anything that seems off, please let me know.

And now some technical details for those who are curious...

The original version of BBGM did not have a live sim feature, so you couldn't see the play-by-play. All you could see was the final box score. I still implemented the underlying simulation as play-by-play because I thought that would be easiest, the play-by-play didn't need to have a realistic clock. And that was also easiest. So I made a ton of simplifications related to the game clock - all possessions were the same length, game situation didn't affect substitutions, teams didn't do any clock management, teams didn't act differently depending on the score/clock, etc.

When I intially made the live sim UI many years ago, most of those simplifications still existed. Over the years I have gradually fixed some of them. Like I added special logic for teams playing faster when they're down late, intentionally fouling to prevent the offense from running off the clock, playing their best players late in close games, playing their bench players in blowouts, and trying for 2-for-1s at the end of periods.

Despite that, there were still a lot of weird situations related to the game clock that were difficult to fix without getting rid of one big assumption that had always been in my code - that the amount of time a possession takes is computed up front, and then you figure out what actually happens in the possession after that. With this update, that old unrealistic situation is now gone. Instead, the clock advances gradually through a possession based on the actual events in the game. It was a decent amount of effort to get that all working, but it made some things a lot easier.

Like how in the old version, you'd too often see fouls with 0 seconds on the clock. In real life, a foul stops the clock, so the only time you can get a foul with 0 on the clock is if the foul occurs after the shot. Which can happen, but it's rare. In BBGM, the clock didn't stop on a foul since the possession time was precomputed. So you'd get all these weird fouls with 0 seconds on the clock. Fixing that in the old version would have been complicated... I'd need some way to adjust the precomputed possession time after the fact. Messy. Now it's simply - just set isClockRunning to false when a foul happens, and it all just works. Clock stops when a foul happens, and you only get a foul with 0 on the clock for a very rare buzzer beater where the foul happens after the shot.

It's a similar story for a lot of the above stuff. It was all much easier to do after changing how the clock worked.

Similarly, changes to the play-by-play got easier after the last update where I rewrote how the play-by-play text generation happened in BBGM and FBGM (baseball and hockey already were better since those are newer games, but for a long time I dreaded going back to fix my old basketball and football game sim code). So that prior update also enabled all of the changes above where more detail was added to the play-by-play.

Overall, my game sim code is still too messy. The basketball simulation code is the oldest part of the codebase, and it shows! But the last two updates have been really nice to do, since I am getting some synergy between cleaning up old code (motivated by making the simulation better) and improving the simulation (which is easier after cleaning up code).