Do you know what it is?

Yes, this is a log-or-something text file, but more importantly – this is something that I had in mind when starting this project. It’s a legit football game generated by Football Manager, presented in a debug form. Pretty cool if you have been wanting it for the last 3 months, believe me.

Why it’s cool

From this point, it’s really easy to add to the game generation. As mentioned before, a game generates actions (dubbed #1, #2, etc.), and actions generate phases ([Snap], [Run], [Tackle] etc).

There is some logic related to generating phases (eg. which run ends with a tackle and which one ends with a touchdown), but more general computations (eg. which attempt is it going to be) are calculated on the action or game level. Therefore, If I want to add a new phase to the game or change an existing one, I should be able to do this inside only that phase generator.

Why so late

This time it took 28 commits across 2 weeks, really. Some commits are big, being solid, but much needed refactoring, outcomes of many-hour sittings.

The part that took much time was “progress” with the ball on the pitch. Namely, the progress can mean moving the ball to the left, or to the right. This depends on which team is facing where at any given moment, and that in turn changes constantly during the game. And it’s important to do it right because core functionalities like touchdown or first-down decisions depend on it.

The problem couldn’t have been postponed, because during kickoff – the first phase of each game – the ball is received and already now progress is being flipped. So very early in the game, we should be ready for flipping progress. And bear in mind that the progress flips with every turnover.

I’m fairly happy about the solution to this problem. It has been delegated to Markers and Progress (and Pseudomarkers) classes, each of them existing in two formats – Countup (where progress means more yards) and Countdown (where progress means fewer yards). For example:


class MarkerCountdown
  def initialize(first_down_yards:)
    @first_down_yards = first_down_yards
    @target = first_down_yards.from_left - 10

  attr_reader :first_down_yards, :target

  def crossed?(yards)
    yards.from_left < target

  def starting_progress


class ProgressCountdown
  def to_yards(progress_num)

  def to_range(first, last, yards), -first, -yards)

  def flip

  def touchdown?(yards_in_pitch)
    yards_in_pitch <= 0

  def ==(o)
    self.class == o.class


Tests do pay off. I did a lot of redesign like extracting MatchState out of MatchGenerator class. That would be virtually impossible without rewriting from scratch both of them if I didn’t have tests.

My tests have gaps, but most importantly – I can trust them. Whenever I feel I might need more of the safety net, I do add tests, simple as that.

Some interesting pieces of my current testing env:

Stay tunes, it’s exciting time for all the (American) football fans!