Skip to content

Commit 4156c3e

Browse files
committed
Handle failed penalty kicks
1 parent 75dd353 commit 4156c3e

20 files changed

+1723
-444
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package engine
2+
3+
import (
4+
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/geom"
5+
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/state"
6+
)
7+
8+
func (e *Engine) processPenalty() {
9+
if *e.currentState.GameState.Type == state.GameState_PENALTY &&
10+
goDur(e.currentState.CurrentActionTimeRemaining) < 0 {
11+
var location *geom.Vector2
12+
if e.gcState.TrackerStateGc.Ball != nil {
13+
location = e.gcState.TrackerStateGc.Ball.Pos.ToVector2()
14+
}
15+
e.Enqueue(createGameEventChange(state.GameEvent_PENALTY_KICK_FAILED, state.GameEvent{
16+
Event: &state.GameEvent_PenaltyKickFailed_{
17+
PenaltyKickFailed: &state.GameEvent_PenaltyKickFailed{
18+
ByTeam: e.currentState.GameState.ForTeam,
19+
Location: location,
20+
},
21+
},
22+
}))
23+
}
24+
}

internal/app/engine/process_tick.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,27 @@ func (e *Engine) processTick() {
4040
addDur(e.currentState.TeamInfo(*e.currentState.Command.ForTeam).TimeoutTimeLeft, -delta)
4141
}
4242

43+
if goDur(e.currentState.CurrentActionTimeRemaining) < 0 {
44+
switch *e.currentState.GameState.Type {
45+
case state.GameState_KICKOFF, state.GameState_FREE_KICK:
46+
revertible := false
47+
e.Enqueue(&statemachine.Change{
48+
Origin: &changeOriginEngine,
49+
Revertible: &revertible,
50+
Change: &statemachine.Change_NewGameState{
51+
NewGameState: &statemachine.NewGameState{
52+
GameState: state.NewGameStateNeutral(state.GameState_RUNNING),
53+
},
54+
},
55+
})
56+
}
57+
}
58+
4359
e.noProgressDetector.process()
4460
e.ballPlacementCoordinator.process()
4561
e.processContinue()
4662
e.processBotNumber()
63+
e.processPenalty()
4764

4865
stateCopy := e.currentState.Clone()
4966
for _, hook := range e.hooks {

internal/app/state/gamestate.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package state
2+
3+
func NewGameStateNeutral(t GameState_Type) *GameState {
4+
return &GameState{
5+
Type: &t,
6+
ForTeam: nil,
7+
}
8+
}
9+
10+
func NewGameStateWithTeam(t GameState_Type, forTeam Team) *GameState {
11+
return &GameState{
12+
Type: &t,
13+
ForTeam: &forTeam,
14+
}
15+
}

internal/app/state/ssl_gc_game_event.pb.go

Lines changed: 254 additions & 181 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/app/state/ssl_gc_state.pb.go

Lines changed: 208 additions & 85 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/app/state/state.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ func NewState() (s *State) {
1212
s = new(State)
1313
s.Stage = new(Referee_Stage)
1414
s.Command = NewCommandNeutral(Command_HALT)
15+
s.GameState = NewGameStateNeutral(GameState_HALT)
1516
s.StageTimeElapsed = new(duration.Duration)
1617
s.StageTimeLeft = new(duration.Duration)
1718
s.MatchTimeStart = new(timestamp.Timestamp)

internal/app/statemachine/change_ballplacement.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@ import (
77

88
func (s *StateMachine) processChangeStartBallPlacement(newState *state.State) (changes []*Change) {
99

10-
if newState.PlacementPos == nil || noTeamCanPlaceBall(newState) {
10+
if newState.NextCommand == nil || newState.PlacementPos == nil || noTeamCanPlaceBall(newState) {
1111
log.Print("placement not possible, human ref must help out")
12-
changes = append(changes, s.newCommandChange(state.NewCommandNeutral(state.Command_HALT)))
12+
changes = append(changes, s.createCommandChange(state.NewCommandNeutral(state.Command_HALT)))
1313
return
1414
}
1515

16-
if newState.NextCommand != nil &&
17-
(*newState.NextCommand.Type == state.Command_PENALTY || *newState.NextCommand.Type == state.Command_KICKOFF) {
16+
if *newState.NextCommand.Type == state.Command_PENALTY || *newState.NextCommand.Type == state.Command_KICKOFF {
1817
log.Printf("Human ref places the ball for %v", *newState.NextCommand)
19-
changes = append(changes, s.newCommandChange(state.NewCommandNeutral(state.Command_HALT)))
18+
changes = append(changes, s.createCommandChange(state.NewCommandNeutral(state.Command_HALT)))
2019
}
2120

2221
var teamInFavor state.Team
@@ -31,17 +30,17 @@ func (s *StateMachine) processChangeStartBallPlacement(newState *state.State) (c
3130

3231
if !*newState.TeamInfo(teamInFavor).CanPlaceBall {
3332
log.Printf("Placement for team %v is disabled, team %v places the ball for team %v", teamInFavor, teamInFavor.Opposite(), teamInFavor)
34-
changes = append(changes, s.newCommandChange(state.NewCommand(state.Command_BALL_PLACEMENT, teamInFavor.Opposite())))
33+
changes = append(changes, s.createCommandChange(state.NewCommand(state.Command_BALL_PLACEMENT, teamInFavor.Opposite())))
3534
} else if !*newState.TeamInfo(teamInFavor).BallPlacementFailuresReached {
3635
log.Printf("Team %v places the ball for itself", teamInFavor)
37-
changes = append(changes, s.newCommandChange(state.NewCommand(state.Command_BALL_PLACEMENT, teamInFavor)))
36+
changes = append(changes, s.createCommandChange(state.NewCommand(state.Command_BALL_PLACEMENT, teamInFavor)))
3837
} else if ballLeftField(newState) {
3938
log.Printf("Team %v reached the maximum allowed placement failures and ball left the field. Team %v places ball for its own free kick", teamInFavor, teamInFavor.Opposite())
4039
newState.NextCommand = state.NewCommand(state.Command_DIRECT, teamInFavor.Opposite())
41-
changes = append(changes, s.newCommandChange(state.NewCommand(state.Command_BALL_PLACEMENT, teamInFavor.Opposite())))
40+
changes = append(changes, s.createCommandChange(state.NewCommand(state.Command_BALL_PLACEMENT, teamInFavor.Opposite())))
4241
} else {
4342
log.Printf("Team %v reached the maximum allowed placement failures, but ball has not left the field. Human ref places the ball for team %v", teamInFavor, teamInFavor)
44-
changes = append(changes, s.newCommandChange(state.NewCommandNeutral(state.Command_HALT)))
43+
changes = append(changes, s.createCommandChange(state.NewCommandNeutral(state.Command_HALT)))
4544
}
4645

4746
return

internal/app/statemachine/change_command.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
)
88

99
func (s *StateMachine) processChangeNewCommand(newState *state.State, newCommand *NewCommand) (changes []*Change) {
10+
newState.GameState = s.newGameState(newState, newCommand)
1011
newState.Command = newCommand.Command
1112

1213
switch *newState.Command.Type {
@@ -55,3 +56,33 @@ func (s *StateMachine) nextCommandForCommand(newState *state.State) (command *st
5556

5657
return newState.NextCommand
5758
}
59+
60+
func (s *StateMachine) newGameState(newState *state.State, newCommand *NewCommand) *state.GameState {
61+
switch *newCommand.Command.Type {
62+
case state.Command_HALT:
63+
return state.NewGameStateNeutral(state.GameState_HALT)
64+
case state.Command_STOP:
65+
return state.NewGameStateNeutral(state.GameState_STOP)
66+
case state.Command_NORMAL_START:
67+
// Keep previous state
68+
return newState.GameState
69+
case state.Command_FORCE_START:
70+
return state.NewGameStateNeutral(state.GameState_RUNNING)
71+
case state.Command_DIRECT:
72+
return state.NewGameStateWithTeam(state.GameState_FREE_KICK, *newCommand.Command.ForTeam)
73+
case state.Command_INDIRECT:
74+
return state.NewGameStateWithTeam(state.GameState_FREE_KICK, *newCommand.Command.ForTeam)
75+
case state.Command_KICKOFF:
76+
return state.NewGameStateWithTeam(state.GameState_KICKOFF, *newCommand.Command.ForTeam)
77+
case state.Command_PENALTY:
78+
return state.NewGameStateWithTeam(state.GameState_PENALTY, *newCommand.Command.ForTeam)
79+
case state.Command_TIMEOUT:
80+
return state.NewGameStateWithTeam(state.GameState_TIMEOUT, *newCommand.Command.ForTeam)
81+
case state.Command_BALL_PLACEMENT:
82+
return state.NewGameStateWithTeam(state.GameState_BALL_PLACEMENT, *newCommand.Command.ForTeam)
83+
case state.Command_UNKNOWN:
84+
return state.NewGameStateNeutral(state.GameState_UNKNOWN)
85+
default:
86+
return state.NewGameStateNeutral(state.GameState_UNKNOWN)
87+
}
88+
}

internal/app/statemachine/change_common.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package statemachine
22

33
import "github.com/RoboCup-SSL/ssl-game-controller/internal/app/state"
44

5-
// newCommandChange creates a change with a new command
6-
func (s *StateMachine) newCommandChange(command *state.Command) *Change {
5+
// createCommandChange creates a change with a new command
6+
func (s *StateMachine) createCommandChange(command *state.Command) *Change {
77
return &Change{
88
Change: &Change_NewCommand{
99
NewCommand: &NewCommand{
@@ -12,3 +12,17 @@ func (s *StateMachine) newCommandChange(command *state.Command) *Change {
1212
},
1313
}
1414
}
15+
16+
// createGameEventChange creates a change with a new game event
17+
func createGameEventChange(eventType state.GameEvent_Type, event state.GameEvent) *Change {
18+
event.Type = &eventType
19+
event.Origin = []string{changeOriginStateMachine}
20+
return &Change{
21+
Origin: &changeOriginStateMachine,
22+
Change: &Change_AddGameEvent{
23+
AddGameEvent: &AddGameEvent{
24+
GameEvent: &event,
25+
},
26+
},
27+
}
28+
}

internal/app/statemachine/change_continue.go

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,26 @@ func (s *StateMachine) processChangeContinue(newState *state.State) (changes []*
2020

2121
if *newState.Command.Type == state.Command_HALT {
2222
log.Printf("Continue with STOP after HALT")
23-
changes = append(changes, s.newCommandChange(state.NewCommandNeutral(state.Command_STOP)))
23+
changes = append(changes, s.createCommandChange(state.NewCommandNeutral(state.Command_STOP)))
2424
} else if newState.NextCommand != nil {
2525
log.Printf("Continue with next command: %v", *newState.NextCommand)
26-
changes = append(changes, s.newCommandChange(newState.NextCommand))
26+
changes = append(changes, s.createCommandChange(newState.NextCommand))
2727
} else if *newState.Command.Type != state.Command_HALT {
2828
log.Println("Halting the game as there is no known next command to continue with")
29-
changes = append(changes, s.newCommandChange(state.NewCommandNeutral(state.Command_HALT)))
29+
changes = append(changes, s.createCommandChange(state.NewCommandNeutral(state.Command_HALT)))
3030
}
3131
return
3232
}
3333

3434
// botSubstitutionIntentEventChange creates a new change for bot substitution
3535
func (s *StateMachine) botSubstitutionIntentEventChange(byTeam state.Team) *Change {
3636
eventType := state.GameEvent_BOT_SUBSTITUTION
37-
return &Change{
38-
Change: &Change_AddGameEvent{
39-
AddGameEvent: &AddGameEvent{
40-
GameEvent: &state.GameEvent{
41-
Type: &eventType,
42-
Event: &state.GameEvent_BotSubstitution_{
43-
BotSubstitution: &state.GameEvent_BotSubstitution{
44-
ByTeam: &byTeam,
45-
},
46-
},
47-
},
37+
return createGameEventChange(state.GameEvent_BOT_SUBSTITUTION, state.GameEvent{
38+
Type: &eventType,
39+
Event: &state.GameEvent_BotSubstitution_{
40+
BotSubstitution: &state.GameEvent_BotSubstitution{
41+
ByTeam: &byTeam,
4842
},
4943
},
50-
}
44+
})
5145
}

0 commit comments

Comments
 (0)