The first steps of the proposed backtracking were to figure out what was currently happening in STP. Whilst browsing through the files, patterns became clear that were not obvious with the structure of the current file. Therefore, some refactoring of files and renames were made to improve the readability of STP.

CMDragons proposed a split between Active and non-Active tactics. They suggest that tactics that involve ball manipulations are Active tactics and if they would succeed, it would result in a trigger that transitions to all roles of a play. This had already been implemented as the ’EndTactic’, however, the split between tactics that involve ball manipulation was not clear from outside the tactic itself.

This split was introduced in the STP structure as Passive and Active, and was stretched over Roles as well. The definition of Passive and Active is as followed:

Passive Tactic and Roles that do not influence the state of a play. If a passive Tactic succeeds, this information is not of importance for the other roles. Examples of Passive roles are; blockers, defenders and Role that involve positioning. Examples of Passive tactics are; blocking the ball and going into formation. None of these parts involves manipulating the ball.

Passive currently includes:


  • BallAvoider
  • BallDefender
  • Formation
  • Halt
  • RobotDefender
  • Waller


  • AvoidBall
  • BallStandBack
  • BlockBall
  • BlockRobot
  • Formation
  • Halt
  • Walling

Active Tactics and Roles that do influence the state of the play. The succession of an Active Tactic and Role should probably result in the play changing. Example of Active roles is; ball-stealer, ball-getter and ball-passer. Examples of Active tactics are; drive with a ball, shoot at a position and receive the ball.

Active currently includes:


  • Attacker
  • BallGetter
  • BallPlacer
  • BallReflector
  • FreeKickTaker
  • Harasser
  • Passer
  • PassReceiver


  • ChipAtPos
  • DriveWithBall
  • GetBall
  • GetBehindBallInDirection
  • KickAtPos
  • Receive
  • ShootAtPos

Plays can be split effectively by sorting them on the state of the game with respect to the ball. There are 3 states, the ball is in possession of this team, the ball is not in possession of any team and the ball is in possession of the enemy team. An extra state is added for the referee states, i.e. free-kick, ball placement and timeouts.

Offensive When the ball is in possession of the team, the logical play would be to try to score with the ball, therefore the ’offensive’. All plays that assume that the ball is our possession are categorized under this state.

Offensive currently includes:

  • Attack
  • AttackingPass

Contested When the ball is free from any team, the ball is ’contested’ as Both teams will try to get possession of the ball. If the evaluations of the game are done correctly, passes between robots should not be seen as the ball is free. All plays that assume the ball is free are categorized under this state.

Defensive When the ball is in possession of the enemy team, the play will be to defend the goal or steal the ball. All plays that assume the ball is in possession of the enemy team are categorized under this state.

Defensive currently includes:

  • DefendPass
  • DefendShot

Referee Specific States that the referee calls upon are states that will only be used in specific plays. All these plays are categorized under this state.

Referee Specific currently includes:

  • AggressiveStopFormation
  • BallPlacementThem
  • BallPlacementUs
  • DefensiveStopFormation
  • FreeKickThem
  • Halt
  • KickOffThem
  • KickOffThemPrepare
  • KickOffUs
  • KickOffUsPrepare
  • PenaltyThem
  • PenaltyThemPrepare
  • PenaltyUs
  • PenaltyUsPrepare

One of the goals was to keep the play as simple as possible by only using building blocks within the play. The building blocks include the usage of generalized roles, but also generalized flags for these roles, game state evaluations, positioning calculations, shooting calculations and passing calculations. Previously, these were copied over from one play to another, cluttering up the plays and making the plays seem more complex than needed. The category ’computations’ was added to hold all the calculations that can be made in the play. More information about how positioning computations are done will be explained further below.

Likewise, ’evaluations’ were added that should hold all evaluations that are needed in the play. The old invariant system (that returned a score of 0-255 based on its true-ness) looked at the game state. This seemed illogical to be just for game states and therefore the refactor from invariants to evaluations were made. Within evaluations, a score is given based on evaluating the input parameters and mapping them to a 0-255 range with a piece-wise linear function. For example, when evaluating the openness of a location, all the distance gathering of the location is done in the computation which refers that information to the evaluation The evaluation will then make a score based on the given parameters (i.e. summing them up) and map the result to the correct range.

Example of a piece-wise function, mapping an input of x to the uint8-t score of the evaluations