Add player positioning and basic draft logic

This commit is contained in:
Hamcha 2019-06-26 14:59:55 +02:00
parent cd04155257
commit 25d05402c1
2 changed files with 128 additions and 1 deletions

View file

@ -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)

View file

@ -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"`
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
}
}
}
}