Skip to content

Commit c4c992b

Browse files
committed
[bugfix,test] Added a lot more tests and fixed some placement bugs
1 parent 5b9cfac commit c4c992b

16 files changed

+1032
-68
lines changed

internal/app/controller/engine.go

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,15 @@ func (e *Engine) CommandForEvent(event *GameEvent) (command RefCommand, forTeam
171171
command = CommandUnknown
172172
forTeam = TeamUnknown
173173

174-
if event.IsSecondary() {
174+
primaryGameEvent := e.State.PrimaryGameEvent()
175+
if (event.IsSecondary() && event.Type != GameEventPlacementFailed) || primaryGameEvent == nil {
175176
return
176177
}
177178

178-
if e.State.bothTeamsCanPlaceBall() && e.State.ballPlacementFailedBefore() && event.Type.resultsFromBallLeavingField() {
179+
if e.State.bothTeamsCanPlaceBall() &&
180+
e.State.ballPlacementFailedBefore() &&
181+
!e.allTeamsFailedPlacement() &&
182+
primaryGameEvent.Type.resultsFromBallLeavingField() {
179183
// A failed placement will result in an indirect free kick for the opposing team.
180184
command = CommandIndirect
181185
forTeam = event.ByTeam()
@@ -222,7 +226,7 @@ func (e *Engine) CommandForEvent(event *GameEvent) (command RefCommand, forTeam
222226

223227
if e.State.Division == config.DivA && // For division A
224228
!e.State.TeamState[forTeam].CanPlaceBall && // If team in favor can not place the ball
225-
event.Type.resultsFromBallLeavingField() { // event is caused by the ball leaving the field
229+
primaryGameEvent.Type.resultsFromBallLeavingField() { // event is caused by the ball leaving the field
226230
// All free kicks that were a result of the ball leaving the field, are awarded to the opposing team.
227231
forTeam = forTeam.Opposite()
228232
}
@@ -661,20 +665,28 @@ func (e *Engine) placeBall(event *GameEvent) {
661665
// placement not possible, human ref must help out
662666
e.SendCommand(CommandHalt, "")
663667
return
664-
} else if e.State.Division == config.DivB && // For division B
665-
!e.State.TeamState[teamInFavor].CanPlaceBall { // If team in favor can not place the ball
666-
// Rule: [...] the team is allowed to bring the ball into play, after the ball was placed by the opposing team.
667-
e.SendCommand(CommandBallPlacement, teamInFavor.Opposite())
668-
} else if e.State.bothTeamsCanPlaceBall() && e.State.ballPlacementFailedBefore() && event.Type.resultsFromBallLeavingField() {
669-
// Rule: A failed placement will result in an indirect free kick for the opposing team.
670-
e.SendCommand(CommandBallPlacement, teamInFavor.Opposite())
671-
} else if e.State.Division == config.DivA && // For division A
668+
}
669+
670+
if e.State.Division == config.DivA && // For division A
672671
!e.State.TeamState[teamInFavor].CanPlaceBall && // If team in favor can not place the ball
672+
e.State.TeamState[teamInFavor.Opposite()].CanPlaceBall && // If opponent team can place the ball
673673
event.Type.resultsFromBallLeavingField() {
674674
// Rule: All free kicks that were a result of the ball leaving the field, are awarded to the opposing team.
675675
e.SendCommand(CommandBallPlacement, teamInFavor.Opposite())
676-
} else {
676+
} else if e.State.Division == config.DivB && // For division B
677+
!e.State.TeamState[teamInFavor].CanPlaceBall && // If team in favor can not place the ball
678+
e.State.TeamState[teamInFavor.Opposite()].CanPlaceBall && // If opponent team can place the ball
679+
event.Type != GameEventPlacementFailed { // opponent team has not failed recently
680+
// Rule: [...] the team is allowed to bring the ball into play, after the ball was placed by the opposing team.
681+
e.SendCommand(CommandBallPlacement, teamInFavor.Opposite())
682+
} else if e.State.TeamState[teamInFavor].CanPlaceBall &&
683+
!e.allTeamsFailedPlacement() {
684+
// If team can place ball, let it place
677685
e.SendCommand(CommandBallPlacement, teamInFavor)
686+
} else {
687+
// If team can not place ball, human ref has to help out
688+
e.SendCommand(CommandHalt, "")
689+
return
678690
}
679691
e.setCurrentActionTimeout(e.config.BallPlacementTime)
680692
}

internal/app/controller/state.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -491,10 +491,6 @@ func (s State) BotSubstitutionIntend() Team {
491491
}
492492

493493
func (s *State) PrimaryGameEvent() *GameEvent {
494-
if len(s.GameEvents) == 0 {
495-
return nil
496-
}
497-
498494
if event := s.GetFirstGameEvent(GameEventMultipleCards); event != nil {
499495
// only this event causes a penalty kick and must be prioritized.
500496
return event
@@ -504,7 +500,14 @@ func (s *State) PrimaryGameEvent() *GameEvent {
504500
// Goal overrides everything else
505501
return event
506502
}
507-
return s.GameEvents[len(s.GameEvents)-1]
503+
504+
for i := len(s.GameEvents) - 1; i >= 0; i-- {
505+
gameEvent := s.GameEvents[i]
506+
if !gameEvent.IsSecondary() && gameEvent.Type != GameEventPlacementFailed {
507+
return gameEvent
508+
}
509+
}
510+
return nil
508511
}
509512

510513
func newTeamInfo() (t TeamInfo) {
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Situation:
2+
# Ball left field by Yellow
3+
#
4+
# Division: A
5+
#
6+
# Who can place?
7+
# both teams
8+
#
9+
# Ball left field?
10+
# yes
11+
#
12+
# Who succeeds?
13+
# Opponent team (one failure)
14+
# -> yellow
15+
#
16+
# Special case?
17+
# Yes (second try, both teams can place, ball left field before)
18+
# Opponent (yellow) is awarded an indirect free kick, because the first team has failed.
19+
#
20+
initialState:
21+
stage: First Half
22+
command: forceStart
23+
division: DivA
24+
stageTimeLeft: 5m
25+
teamState:
26+
Yellow:
27+
ballPlacementFailures: 2
28+
Blue:
29+
ballPlacementFailures: 3
30+
transitions:
31+
- event:
32+
gameEvent:
33+
type: ballLeftFieldGoalLine
34+
details:
35+
ballleftfieldgoalline:
36+
byteam: 1 # Yellow
37+
bybot: 0
38+
location:
39+
x: 6.0
40+
y: 4.0
41+
expectedStateDiff:
42+
command: ballPlacement
43+
commandFor: Blue
44+
nextCommand: direct
45+
nextCommandFor: Blue
46+
currentActionDeadline: "2010-01-01T00:00:30Z"
47+
currentActionTimeRemaining: 30s
48+
placementPos:
49+
x: 5.8
50+
y: 4.3
51+
gameEvents:
52+
- type: ballLeftFieldGoalLine
53+
details:
54+
ballleftfieldgoalline:
55+
byteam: 1 # Yellow
56+
bybot: 0
57+
location:
58+
x: 6.0
59+
y: 4.0
60+
- tick: 1s # make sure that the stage time is not proceeded
61+
expectedStateDiff:
62+
currentActionTimeRemaining: 29s
63+
placementPos:
64+
x: 5.8
65+
y: 4.3
66+
- event:
67+
gameEvent:
68+
type: placementFailed
69+
details:
70+
placementfailed:
71+
byteam: 2 # Blue
72+
remainingdistance: 1.0
73+
expectedStateDiff:
74+
command: ballPlacement
75+
commandFor: Yellow
76+
nextCommand: indirect
77+
nextCommandFor: Yellow
78+
currentActionDeadline: "2010-01-01T00:00:31Z"
79+
currentActionTimeRemaining: 30s
80+
placementPos:
81+
x: 5.8
82+
y: 4.3
83+
gameEvents:
84+
- type: ballLeftFieldGoalLine
85+
details:
86+
ballleftfieldgoalline:
87+
byteam: 1 # Yellow
88+
bybot: 0
89+
location:
90+
x: 6.0
91+
y: 4.0
92+
- type: placementFailed
93+
details:
94+
placementfailed:
95+
byteam: 2 # Blue
96+
remainingdistance: 1.0
97+
teamState:
98+
Blue:
99+
ballPlacementFailures: 4
100+
- tick: 1s # make sure that the stage time is not proceeded
101+
expectedStateDiff:
102+
currentActionTimeRemaining: 29s
103+
placementPos:
104+
x: 5.8
105+
y: 4.3
106+
- event:
107+
gameEvent:
108+
type: placementSucceeded
109+
details:
110+
placementsucceeded:
111+
byteam: 1 # Yellow
112+
timetaken: 1.0
113+
precision: 0.01
114+
expectedStateDiff:
115+
command: indirect
116+
commandFor: Yellow
117+
nextCommand: ""
118+
nextCommandFor: ""
119+
currentActionDeadline: "2010-01-01T00:00:07Z"
120+
currentActionTimeRemaining: 5s
121+
gameEvents: []
122+
teamState:
123+
Yellow:
124+
ballPlacementFailures: 0
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Situation:
2+
# Ball left field by Yellow
3+
#
4+
# Division: B
5+
#
6+
# Who can place?
7+
# both teams
8+
#
9+
# Ball left field?
10+
# yes
11+
#
12+
# Who succeeds?
13+
# Opponent team (one failure)
14+
# -> yellow
15+
#
16+
# Special case?
17+
# Yes (second try, both teams can place, ball left field before)
18+
# Opponent (yellow) is awarded an indirect free kick, because the first team has failed.
19+
#
20+
initialState:
21+
stage: First Half
22+
command: forceStart
23+
division: DivB
24+
stageTimeLeft: 5m
25+
teamState:
26+
Yellow:
27+
ballPlacementFailures: 2
28+
Blue:
29+
ballPlacementFailures: 3
30+
transitions:
31+
- event:
32+
gameEvent:
33+
type: ballLeftFieldGoalLine
34+
details:
35+
ballleftfieldgoalline:
36+
byteam: 1 # Yellow
37+
bybot: 0
38+
location:
39+
x: 4.5
40+
y: 3.0
41+
expectedStateDiff:
42+
command: ballPlacement
43+
commandFor: Blue
44+
nextCommand: direct
45+
nextCommandFor: Blue
46+
currentActionDeadline: "2010-01-01T00:00:30Z"
47+
currentActionTimeRemaining: 30s
48+
placementPos:
49+
x: 4.3
50+
y: 2.8
51+
gameEvents:
52+
- type: ballLeftFieldGoalLine
53+
details:
54+
ballleftfieldgoalline:
55+
byteam: 1 # Yellow
56+
bybot: 0
57+
location:
58+
x: 4.5
59+
y: 3.0
60+
- tick: 1s # make sure that the stage time is not proceeded
61+
expectedStateDiff:
62+
currentActionTimeRemaining: 29s
63+
placementPos:
64+
x: 4.3
65+
y: 2.8
66+
- event:
67+
gameEvent:
68+
type: placementFailed
69+
details:
70+
placementfailed:
71+
byteam: 2 # Blue
72+
remainingdistance: 1.0
73+
expectedStateDiff:
74+
command: ballPlacement
75+
commandFor: Yellow
76+
nextCommand: indirect
77+
nextCommandFor: Yellow
78+
currentActionDeadline: "2010-01-01T00:00:31Z"
79+
currentActionTimeRemaining: 30s
80+
placementPos:
81+
x: 4.3
82+
y: 2.8
83+
gameEvents:
84+
- type: ballLeftFieldGoalLine
85+
details:
86+
ballleftfieldgoalline:
87+
byteam: 1 # Yellow
88+
bybot: 0
89+
location:
90+
x: 4.5
91+
y: 3.0
92+
- type: placementFailed
93+
details:
94+
placementfailed:
95+
byteam: 2 # Blue
96+
remainingdistance: 1.0
97+
teamState:
98+
Blue:
99+
ballPlacementFailures: 4
100+
- tick: 1s # make sure that the stage time is not proceeded
101+
expectedStateDiff:
102+
currentActionTimeRemaining: 29s
103+
placementPos:
104+
x: 4.3
105+
y: 2.8
106+
- event:
107+
gameEvent:
108+
type: placementSucceeded
109+
details:
110+
placementsucceeded:
111+
byteam: 1 # Yellow
112+
timetaken: 1.0
113+
precision: 0.01
114+
expectedStateDiff:
115+
command: indirect
116+
commandFor: Yellow
117+
nextCommand: ""
118+
nextCommandFor: ""
119+
currentActionDeadline: "2010-01-01T00:00:12Z"
120+
currentActionTimeRemaining: 10s
121+
gameEvents: []
122+
teamState:
123+
Yellow:
124+
ballPlacementFailures: 0

0 commit comments

Comments
 (0)