Add player positioning and basic draft logic
This commit is contained in:
parent
cd04155257
commit
25d05402c1
2 changed files with 128 additions and 1 deletions
|
@ -4,9 +4,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.fromouter.space/Artificiale/moa/sd"
|
"git.fromouter.space/Artificiale/moa/sd"
|
||||||
"git.fromouter.space/mcg/cardgage/client/bot"
|
"git.fromouter.space/mcg/cardgage/client/bot"
|
||||||
|
@ -31,6 +33,9 @@ func main() {
|
||||||
}, logger)
|
}, logger)
|
||||||
defer registrar.Deregister()
|
defer registrar.Deregister()
|
||||||
|
|
||||||
|
// Seed RNG
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
// Initialize consul client for service discovery
|
// Initialize consul client for service discovery
|
||||||
sd.InitClient(*consulAddr)
|
sd.InitClient(*consulAddr)
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,28 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
"git.fromouter.space/mcg/draft"
|
"git.fromouter.space/mcg/draft"
|
||||||
"git.fromouter.space/mcg/draft/mlp"
|
"git.fromouter.space/mcg/draft/mlp"
|
||||||
"git.fromouter.space/mcg/mlp-server-tools/draftbot/bot"
|
"git.fromouter.space/mcg/mlp-server-tools/draftbot/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Session-related errors
|
||||||
|
var (
|
||||||
|
ErrTooManyPlayers = errors.New("too many players")
|
||||||
|
ErrNotEnoughPlayers = errors.New("not enough players")
|
||||||
|
)
|
||||||
|
|
||||||
type session struct {
|
type session struct {
|
||||||
Options draftOptions
|
Options draftOptions
|
||||||
Players map[string]*draft.Player
|
Players map[string]*draft.Player
|
||||||
Bots []*bot.Bot
|
Bots []*bot.Bot
|
||||||
Pod *draft.Pod
|
Pod *draft.Pod
|
||||||
|
|
||||||
|
// Channels for communication while the session is running
|
||||||
|
exit chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Types of drafts
|
// Types of drafts
|
||||||
|
@ -23,8 +34,15 @@ const (
|
||||||
draftI8PCube = "i8pcube"
|
draftI8PCube = "i8pcube"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ways in which players can be positioned along the draft pod
|
||||||
|
const (
|
||||||
|
posRandom = "random" // Place players randomly
|
||||||
|
posEven = "even" // Place players spaced as evenly as possible
|
||||||
|
)
|
||||||
|
|
||||||
type draftOptions struct {
|
type draftOptions struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
Positioning string `json:"positioning"`
|
||||||
|
|
||||||
// Block draft properties
|
// Block draft properties
|
||||||
Block string `json:"block,omitempty"`
|
Block string `json:"block,omitempty"`
|
||||||
|
@ -42,6 +60,7 @@ type draftOptions struct {
|
||||||
|
|
||||||
// Shared
|
// Shared
|
||||||
PackCount int `json:"pack_count,omitempty"` // Set and Cube
|
PackCount int `json:"pack_count,omitempty"` // Set and Cube
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (do draftOptions) getProvider() (draft.PackProvider, error) {
|
func (do draftOptions) getProvider() (draft.PackProvider, error) {
|
||||||
|
@ -84,5 +103,108 @@ func newSession(playerCount int, opt draftOptions) (*session, error) {
|
||||||
return &session{
|
return &session{
|
||||||
Options: opt,
|
Options: opt,
|
||||||
Pod: draft.MakePod(playerCount, provider),
|
Pod: draft.MakePod(playerCount, provider),
|
||||||
|
exit: make(chan bool),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *session) Start() error {
|
||||||
|
// Figure out how many players there are vs spots to be filled
|
||||||
|
spots := len(s.Pod.Players)
|
||||||
|
players := len(s.Players)
|
||||||
|
if players > spots {
|
||||||
|
return ErrTooManyPlayers
|
||||||
|
}
|
||||||
|
|
||||||
|
if players < 1 {
|
||||||
|
return ErrNotEnoughPlayers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign players to their spot on the drafting pod
|
||||||
|
playerSpot := make(map[int]string)
|
||||||
|
|
||||||
|
switch s.Options.Positioning {
|
||||||
|
case posRandom:
|
||||||
|
// Assign a random number to each player
|
||||||
|
for pname := range s.Players {
|
||||||
|
var pos int
|
||||||
|
for {
|
||||||
|
pos = rand.Intn(spots)
|
||||||
|
// Make sure chosen number wasn't already picked
|
||||||
|
if _, ok := playerSpot[pos]; !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
playerSpot[pos] = pname
|
||||||
|
}
|
||||||
|
case posEven:
|
||||||
|
// Space players evenly
|
||||||
|
playerRatio := float64(spots) / float64(players)
|
||||||
|
i := 0
|
||||||
|
for name := range s.Players {
|
||||||
|
pos := int(math.Floor(playerRatio * float64(i)))
|
||||||
|
playerSpot[pos] = name
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign player instances and make bots where needed
|
||||||
|
for i := range s.Pod.Players {
|
||||||
|
if name, ok := playerSpot[i]; ok {
|
||||||
|
s.Players[name] = s.Pod.Players[i]
|
||||||
|
} else {
|
||||||
|
s.Bots = append(s.Bots, bot.MakeBot(s.Pod.Players[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify players of the order
|
||||||
|
//TODO
|
||||||
|
|
||||||
|
// Start handling packs
|
||||||
|
go s.handlePicks()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *session) handlePicks() {
|
||||||
|
// Pack loop, this `for` handles an entire draft session
|
||||||
|
for {
|
||||||
|
err := s.Pod.OpenPacks()
|
||||||
|
if err != nil {
|
||||||
|
if err == draft.ErrNoPacksLeft {
|
||||||
|
// Notify players that the draft is over
|
||||||
|
//TODO
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Pick loop, this `for` handles exactly one round of packs
|
||||||
|
for {
|
||||||
|
// Notify players that their next pack is ready
|
||||||
|
//TODO
|
||||||
|
// Make bots pick their cards
|
||||||
|
for _, bot := range s.Bots {
|
||||||
|
bot.PickNext()
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-s.Pod.ReadyNextPick:
|
||||||
|
// Pass packs around
|
||||||
|
err := s.Pod.NextPacks()
|
||||||
|
if err != nil {
|
||||||
|
if err == draft.ErrNoPendingPack {
|
||||||
|
// No more picks to do for this round of packs, go to next
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
// Something wrong!
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-s.Pod.ReadyNextPack:
|
||||||
|
// Break of pick loop, get next packs
|
||||||
|
break
|
||||||
|
case <-s.exit:
|
||||||
|
// Room closed, exit early
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue