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"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.fromouter.space/Artificiale/moa/sd"
|
||||
"git.fromouter.space/mcg/cardgage/client/bot"
|
||||
|
@ -31,6 +33,9 @@ func main() {
|
|||
}, logger)
|
||||
defer registrar.Deregister()
|
||||
|
||||
// Seed RNG
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
// Initialize consul client for service discovery
|
||||
sd.InitClient(*consulAddr)
|
||||
|
||||
|
|
|
@ -2,17 +2,28 @@ package main
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"math/rand"
|
||||
|
||||
"git.fromouter.space/mcg/draft"
|
||||
"git.fromouter.space/mcg/draft/mlp"
|
||||
"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 {
|
||||
Options draftOptions
|
||||
Players map[string]*draft.Player
|
||||
Bots []*bot.Bot
|
||||
Pod *draft.Pod
|
||||
|
||||
// Channels for communication while the session is running
|
||||
exit chan bool
|
||||
}
|
||||
|
||||
// Types of drafts
|
||||
|
@ -23,8 +34,15 @@ const (
|
|||
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 string `json:"type"`
|
||||
Type string `json:"type"`
|
||||
Positioning string `json:"positioning"`
|
||||
|
||||
// Block draft properties
|
||||
Block string `json:"block,omitempty"`
|
||||
|
@ -42,6 +60,7 @@ type draftOptions struct {
|
|||
|
||||
// Shared
|
||||
PackCount int `json:"pack_count,omitempty"` // Set and Cube
|
||||
|
||||
}
|
||||
|
||||
func (do draftOptions) getProvider() (draft.PackProvider, error) {
|
||||
|
@ -84,5 +103,108 @@ func newSession(playerCount int, opt draftOptions) (*session, error) {
|
|||
return &session{
|
||||
Options: opt,
|
||||
Pod: draft.MakePod(playerCount, provider),
|
||||
exit: make(chan bool),
|
||||
}, 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