rename bots to racers
This commit is contained in:
parent
d70dbd438c
commit
6e7ac9c1ba
16
game/ai.go
16
game/ai.go
|
@ -2,7 +2,7 @@ package game
|
||||||
|
|
||||||
func chooseCommand(s State, teamID int) command {
|
func chooseCommand(s State, teamID int) command {
|
||||||
t := s.Teams[teamID]
|
t := s.Teams[teamID]
|
||||||
h := ActiveBot(t)
|
h := ActiveRacer(t)
|
||||||
if collide(h.Position.Pos+1, h.Position.Lane, s) != nil {
|
if collide(h.Position.Pos+1, h.Position.Lane, s) != nil {
|
||||||
if h.Position.Lane <= t.Lane && h.Position.Lane < NumLanes-1 {
|
if h.Position.Lane <= t.Lane && h.Position.Lane < NumLanes-1 {
|
||||||
return left
|
return left
|
||||||
|
@ -10,17 +10,17 @@ func chooseCommand(s State, teamID int) command {
|
||||||
return right
|
return right
|
||||||
}
|
}
|
||||||
|
|
||||||
var nextBot *Bot
|
var nextRacer *Racer
|
||||||
for i, b := range t.Bots {
|
for i, b := range t.Racers {
|
||||||
if b.ID == h.ID+1 {
|
if b.ID == h.ID+1 {
|
||||||
nextBot = &t.Bots[i]
|
nextRacer = &t.Racers[i]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if nextBot != nil {
|
if nextRacer != nil {
|
||||||
if h.Position.Lane != nextBot.Position.Lane {
|
if h.Position.Lane != nextRacer.Position.Lane {
|
||||||
if abs(nextBot.Position.Pos-h.Position.Pos) < h.v {
|
if abs(nextRacer.Position.Pos-h.Position.Pos) < h.v {
|
||||||
return slowDown
|
return slowDown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func smartChooseHelper(s State, teamID int, depth int) command {
|
||||||
func score(s State, teamID int, depth int) int {
|
func score(s State, teamID int, depth int) int {
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
t := s.Teams[teamID]
|
t := s.Teams[teamID]
|
||||||
b := ActiveBot(t)
|
b := ActiveRacer(t)
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,36 +16,36 @@ func doCommand(cmd command, s State, teamID int) State {
|
||||||
da := 1
|
da := 1
|
||||||
//da += rand.Intn(3) - 1
|
//da += rand.Intn(3) - 1
|
||||||
|
|
||||||
b := ActiveBot(s.Teams[teamID])
|
r := ActiveRacer(s.Teams[teamID])
|
||||||
if b == nil {
|
if r == nil {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
switch cmd {
|
switch cmd {
|
||||||
case speedUp:
|
case speedUp:
|
||||||
b.a += da
|
r.a += da
|
||||||
*b = accelerate(*b)
|
*r = accelerate(*r)
|
||||||
s = updateBot(s, *b)
|
s = updateRacer(s, *r)
|
||||||
case slowDown:
|
case slowDown:
|
||||||
b.a -= da
|
r.a -= da
|
||||||
*b = accelerate(*b)
|
*r = accelerate(*r)
|
||||||
s = updateBot(s, *b)
|
s = updateRacer(s, *r)
|
||||||
case left:
|
case left:
|
||||||
b.Position.Lane++
|
r.Position.Lane++
|
||||||
s = updateBot(s, *b)
|
s = updateRacer(s, *r)
|
||||||
case right:
|
case right:
|
||||||
b.Position.Lane--
|
r.Position.Lane--
|
||||||
s = updateBot(s, *b)
|
s = updateRacer(s, *r)
|
||||||
case clearObstacle:
|
case clearObstacle:
|
||||||
pos := b.Position
|
pos := r.Position
|
||||||
pos.Pos++
|
pos.Pos++
|
||||||
s = removeObstacle(s, pos)
|
s = removeObstacle(s, pos)
|
||||||
b.v = 0
|
r.v = 0
|
||||||
s = updateBot(s, *b)
|
s = updateRacer(s, *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if b := ActiveBot(s.Teams[teamID]); b != nil {
|
if r := ActiveRacer(s.Teams[teamID]); r != nil {
|
||||||
s = moveBot(s, *b)
|
s = moveRacer(s, *r)
|
||||||
}
|
}
|
||||||
s = maybePassBaton(s, teamID)
|
s = maybePassBaton(s, teamID)
|
||||||
|
|
||||||
|
|
108
game/game.go
108
game/game.go
|
@ -13,7 +13,7 @@ func UpdateState(s State, sOld State) State {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range s.Teams {
|
for _, t := range s.Teams {
|
||||||
if b := ActiveBot(t); b != nil && won(*b, s) {
|
if r := ActiveRacer(t); r != nil && won(*r, s) {
|
||||||
log.Printf("team %d won", t.id)
|
log.Printf("team %d won", t.id)
|
||||||
s.GameOver = true
|
s.GameOver = true
|
||||||
}
|
}
|
||||||
|
@ -24,47 +24,47 @@ func UpdateState(s State, sOld State) State {
|
||||||
|
|
||||||
func maybePassBaton(s State, teamID int) State {
|
func maybePassBaton(s State, teamID int) State {
|
||||||
t := s.Teams[teamID]
|
t := s.Teams[teamID]
|
||||||
h := ActiveBot(t)
|
h := ActiveRacer(t)
|
||||||
if h == nil {
|
if h == nil {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, b := range t.Bots {
|
for i, r := range t.Racers {
|
||||||
if h.ID >= b.ID || h.Position.Lane != b.Position.Lane {
|
if h.ID >= r.ID || h.Position.Lane != r.Position.Lane {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if abs(b.Position.Pos-h.Position.Pos) <= PassDistance {
|
if abs(r.Position.Pos-h.Position.Pos) <= PassDistance {
|
||||||
h.v = 0
|
h.v = 0
|
||||||
h.a = 0
|
h.a = 0
|
||||||
s = updateBot(s, *h)
|
s = updateRacer(s, *h)
|
||||||
newH := t.Bots[i]
|
newH := t.Racers[i]
|
||||||
newH.a = baseAccel
|
newH.a = baseAccel
|
||||||
t.Baton.HolderID = newH.ID
|
t.Baton.HolderID = newH.ID
|
||||||
s = updateTeam(s, t)
|
s = updateTeam(s, t)
|
||||||
return updateBot(s, newH)
|
return updateRacer(s, newH)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func ActiveBot(t Team) *Bot {
|
func ActiveRacer(t Team) *Racer {
|
||||||
for _, b := range t.Bots {
|
for _, r := range t.Racers {
|
||||||
if b.ID == t.Baton.HolderID {
|
if r.ID == t.Baton.HolderID {
|
||||||
return &b
|
return &r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateBot(s State, b Bot) State {
|
func updateRacer(s State, r Racer) State {
|
||||||
t := s.Teams[b.TeamID]
|
t := s.Teams[r.TeamID]
|
||||||
for i, bb := range t.Bots {
|
for i, rr := range t.Racers {
|
||||||
if bb.ID == b.ID {
|
if rr.ID == r.ID {
|
||||||
bots := append([]Bot{}, t.Bots[:i]...)
|
racers := append([]Racer{}, t.Racers[:i]...)
|
||||||
bots = append(bots, b)
|
racers = append(racers, r)
|
||||||
bots = append(bots, t.Bots[i+1:]...)
|
racers = append(racers, t.Racers[i+1:]...)
|
||||||
t.Bots = bots
|
t.Racers = racers
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,14 +82,14 @@ func updateTeam(s State, t Team) State {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func destroyBot(s State, b Bot) State {
|
func destroyRacer(s State, r Racer) State {
|
||||||
// insert obstacle where bot was
|
// insert obstacle where racer was
|
||||||
s.Obstacles = append(s.Obstacles, Obstacle{Position: b.Position})
|
s.Obstacles = append(s.Obstacles, Obstacle{Position: r.Position})
|
||||||
|
|
||||||
// spawn bot back at starting position
|
// spawn racer back at starting position
|
||||||
b.Position = b.StartPos
|
r.Position = r.StartPos
|
||||||
|
|
||||||
return updateBot(s, b)
|
return updateRacer(s, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeObstacle(s State, pos Position) State {
|
func removeObstacle(s State, pos Position) State {
|
||||||
|
@ -106,8 +106,8 @@ func removeObstacle(s State, pos Position) State {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func won(b Bot, s State) bool {
|
func won(r Racer, s State) bool {
|
||||||
return b.Position.Pos >= Steps
|
return r.Position.Pos >= Steps
|
||||||
}
|
}
|
||||||
|
|
||||||
func gameOver(s State) bool {
|
func gameOver(s State) bool {
|
||||||
|
@ -120,16 +120,16 @@ func gameOver(s State) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func legalMove(s State, teamID int, cmd command) bool {
|
func legalMove(s State, teamID int, cmd command) bool {
|
||||||
b := ActiveBot(s.Teams[teamID])
|
r := ActiveRacer(s.Teams[teamID])
|
||||||
if b == nil {
|
if r == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch cmd {
|
switch cmd {
|
||||||
case left:
|
case left:
|
||||||
return b.Position.Lane < NumLanes-1
|
return r.Position.Lane < NumLanes-1
|
||||||
case right:
|
case right:
|
||||||
return b.Position.Lane > 0
|
return r.Position.Lane > 0
|
||||||
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -149,14 +149,14 @@ type State struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Team struct {
|
type Team struct {
|
||||||
id int
|
id int
|
||||||
Bots []Bot
|
Racers []Racer
|
||||||
Baton Baton
|
Baton Baton
|
||||||
won bool
|
won bool
|
||||||
Lane int
|
Lane int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Bot struct {
|
type Racer struct {
|
||||||
ID int
|
ID int
|
||||||
TeamID int
|
TeamID int
|
||||||
Position Position
|
Position Position
|
||||||
|
@ -186,24 +186,24 @@ type Obstacle struct {
|
||||||
func NewState() State {
|
func NewState() State {
|
||||||
var teams []Team
|
var teams []Team
|
||||||
for i := 0; i < NumTeams; i++ {
|
for i := 0; i < NumTeams; i++ {
|
||||||
var bots []Bot
|
var racers []Racer
|
||||||
for j := 0; j < numBots; j++ {
|
for j := 0; j < numRacers; j++ {
|
||||||
b := Bot{
|
r := Racer{
|
||||||
ID: i*NumTeams + j,
|
ID: i*NumTeams + j,
|
||||||
TeamID: i,
|
TeamID: i,
|
||||||
StartPos: Position{
|
StartPos: Position{
|
||||||
Lane: i,
|
Lane: i,
|
||||||
Pos: j * (Steps / numBots),
|
Pos: j * (Steps / numRacers),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
b.Position = b.StartPos
|
r.Position = r.StartPos
|
||||||
bots = append(bots, b)
|
racers = append(racers, r)
|
||||||
}
|
}
|
||||||
teams = append(teams, Team{
|
teams = append(teams, Team{
|
||||||
id: i,
|
id: i,
|
||||||
Bots: bots,
|
Racers: racers,
|
||||||
Baton: Baton{HolderID: i * NumTeams},
|
Baton: Baton{HolderID: i * NumTeams},
|
||||||
Lane: i,
|
Lane: i,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,8 +240,8 @@ func randomOpenPosition(ts []Team, os []Obstacle) Position {
|
||||||
|
|
||||||
func positionOpen(pos Position, ts []Team, os []Obstacle) bool {
|
func positionOpen(pos Position, ts []Team, os []Obstacle) bool {
|
||||||
for _, t := range ts {
|
for _, t := range ts {
|
||||||
for _, b := range t.Bots {
|
for _, r := range t.Racers {
|
||||||
if b.Position == pos {
|
if r.Position == pos {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,8 +284,8 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Steps = 50
|
Steps = 50
|
||||||
numBots = 5
|
numRacers = 5
|
||||||
NumTeams = 8
|
NumTeams = 8
|
||||||
NumLanes = NumTeams
|
NumLanes = NumTeams
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
package game
|
package game
|
||||||
|
|
||||||
func accelerate(b Bot) Bot {
|
func accelerate(r Racer) Racer {
|
||||||
if b.a < -MaxA {
|
if r.a < -MaxA {
|
||||||
b.a = -MaxA
|
r.a = -MaxA
|
||||||
}
|
}
|
||||||
if b.a > MaxA {
|
if r.a > MaxA {
|
||||||
b.a = MaxA
|
r.a = MaxA
|
||||||
}
|
}
|
||||||
|
|
||||||
b.v += b.a
|
r.v += r.a
|
||||||
if b.v > MaxV {
|
if r.v > MaxV {
|
||||||
b.v = MaxV
|
r.v = MaxV
|
||||||
}
|
}
|
||||||
if b.v < -MaxV {
|
if r.v < -MaxV {
|
||||||
b.v = -MaxV
|
r.v = -MaxV
|
||||||
}
|
}
|
||||||
|
|
||||||
return b
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func moveBot(s State, b Bot) State {
|
func moveRacer(s State, r Racer) State {
|
||||||
for i := 0; i < b.v; i++ {
|
for i := 0; i < r.v; i++ {
|
||||||
if o := collide(b.Position.Pos+1, b.Position.Lane, s); o != nil {
|
if o := collide(r.Position.Pos+1, r.Position.Lane, s); o != nil {
|
||||||
return destroyBot(s, b)
|
return destroyRacer(s, r)
|
||||||
} else {
|
} else {
|
||||||
b.Position.Pos++
|
r.Position.Pos++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s = updateBot(s, b)
|
s = updateRacer(s, r)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ func collide(pos, lane int, s State) interface{} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, t := range s.Teams {
|
for _, t := range s.Teams {
|
||||||
for _, b := range t.Bots {
|
for _, r := range t.Racers {
|
||||||
if b.Position.Pos == pos && b.Position.Lane == lane {
|
if r.Position.Pos == pos && r.Position.Lane == lane {
|
||||||
return b
|
return r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
gfx/gfx.go
34
gfx/gfx.go
|
@ -29,12 +29,12 @@ type context struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type spriteBank struct {
|
type spriteBank struct {
|
||||||
bot pixel.Picture
|
racer pixel.Picture
|
||||||
obstacle pixel.Picture
|
obstacle pixel.Picture
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSpriteBank() (*spriteBank, error) {
|
func NewSpriteBank() (*spriteBank, error) {
|
||||||
bot, err := loadPicture("shuttle.png")
|
racer, err := loadPicture("shuttle.png")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("load picture: %w", err)
|
return nil, fmt.Errorf("load picture: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func NewSpriteBank() (*spriteBank, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &spriteBank{
|
return &spriteBank{
|
||||||
bot: bot,
|
racer: racer,
|
||||||
obstacle: ob,
|
obstacle: ob,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func Render(rs RenderState, sOld, sNew game.State, w *pixelgl.Window, sb spriteB
|
||||||
tween: float64(rs.Frame) / float64(rs.Frames),
|
tween: float64(rs.Frame) / float64(rs.Frames),
|
||||||
w: w,
|
w: w,
|
||||||
}
|
}
|
||||||
renderBots(ctx, colors, sb.bot)
|
renderRacers(ctx, colors, sb.racer)
|
||||||
renderObstacles(sNew, w, sb.obstacle)
|
renderObstacles(sNew, w, sb.obstacle)
|
||||||
|
|
||||||
rs.Frame++
|
rs.Frame++
|
||||||
|
@ -108,17 +108,17 @@ func renderBackground(w *pixelgl.Window) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderBots(ctx context, colors map[*game.Team]pixel.RGBA, pic pixel.Picture) {
|
func renderRacers(ctx context, colors map[*game.Team]pixel.RGBA, pic pixel.Picture) {
|
||||||
for i, t := range ctx.sNew.Teams {
|
for i, t := range ctx.sNew.Teams {
|
||||||
c := colors[&ctx.sNew.Teams[i]]
|
c := colors[&ctx.sNew.Teams[i]]
|
||||||
for j, bot := range t.Bots {
|
for j, racer := range t.Racers {
|
||||||
oldBot := ctx.sOld.Teams[i].Bots[j]
|
oldRacer := ctx.sOld.Teams[i].Racers[j]
|
||||||
renderBot(ctx, oldBot, bot, c, pic)
|
renderRacer(ctx, oldRacer, racer, c, pic)
|
||||||
}
|
}
|
||||||
|
|
||||||
oldHolder, newHolder := game.ActiveBot(ctx.sOld.Teams[i]), game.ActiveBot(ctx.sNew.Teams[i])
|
oldHolder, newHolder := game.ActiveRacer(ctx.sOld.Teams[i]), game.ActiveRacer(ctx.sNew.Teams[i])
|
||||||
oldPos := lanePos(oldHolder.Position.Pos, oldHolder.Position.Lane, botWidth, ctx.w.Bounds())
|
oldPos := lanePos(oldHolder.Position.Pos, oldHolder.Position.Lane, racerWidth, ctx.w.Bounds())
|
||||||
newPos := lanePos(newHolder.Position.Pos, newHolder.Position.Lane, botWidth, ctx.w.Bounds())
|
newPos := lanePos(newHolder.Position.Pos, newHolder.Position.Lane, racerWidth, ctx.w.Bounds())
|
||||||
|
|
||||||
pos := pixel.Vec{
|
pos := pixel.Vec{
|
||||||
X: oldPos.X + ctx.tween*(newPos.X-oldPos.X),
|
X: oldPos.X + ctx.tween*(newPos.X-oldPos.X),
|
||||||
|
@ -128,12 +128,12 @@ func renderBots(ctx context, colors map[*game.Team]pixel.RGBA, pic pixel.Picture
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderBot(ctx context, oldBot, bot game.Bot, c pixel.RGBA, pic pixel.Picture) {
|
func renderRacer(ctx context, oldRacer, racer game.Racer, c pixel.RGBA, pic pixel.Picture) {
|
||||||
im := imdraw.New(nil)
|
im := imdraw.New(nil)
|
||||||
im.Color = c
|
im.Color = c
|
||||||
|
|
||||||
oldPos := lanePos(oldBot.Position.Pos, oldBot.Position.Lane, botWidth, ctx.w.Bounds())
|
oldPos := lanePos(oldRacer.Position.Pos, oldRacer.Position.Lane, racerWidth, ctx.w.Bounds())
|
||||||
newPos := lanePos(bot.Position.Pos, bot.Position.Lane, botWidth, ctx.w.Bounds())
|
newPos := lanePos(racer.Position.Pos, racer.Position.Lane, racerWidth, ctx.w.Bounds())
|
||||||
|
|
||||||
pos := pixel.Vec{
|
pos := pixel.Vec{
|
||||||
X: oldPos.X + ctx.tween*(newPos.X-oldPos.X),
|
X: oldPos.X + ctx.tween*(newPos.X-oldPos.X),
|
||||||
|
@ -172,14 +172,14 @@ func renderObstacles(s game.State, w *pixelgl.Window, pic pixel.Picture) {
|
||||||
for _, o := range s.Obstacles {
|
for _, o := range s.Obstacles {
|
||||||
//im.Color = colornames.Slategray
|
//im.Color = colornames.Slategray
|
||||||
|
|
||||||
pos := lanePos(o.Position.Pos, o.Position.Lane, botWidth, b)
|
pos := lanePos(o.Position.Pos, o.Position.Lane, racerWidth, b)
|
||||||
|
|
||||||
im.Push(pos)
|
im.Push(pos)
|
||||||
|
|
||||||
im.Clear()
|
im.Clear()
|
||||||
sprite := pixel.NewSprite(pic, pic.Bounds())
|
sprite := pixel.NewSprite(pic, pic.Bounds())
|
||||||
sprite.Draw(w, pixel.IM.Moved(pos))
|
sprite.Draw(w, pixel.IM.Moved(pos))
|
||||||
//im.Circle(float64(botWidth), 0)
|
//im.Circle(float64(racerWidth), 0)
|
||||||
|
|
||||||
im.Draw(w)
|
im.Draw(w)
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,6 @@ func teamColors(ts []game.Team) map[*game.Team]pixel.RGBA {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
botWidth float64 = 17
|
racerWidth float64 = 17
|
||||||
batonWidth float64 = 12
|
batonWidth float64 = 12
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue