commit 50c63067d191400ab3a22982938528b8bbdac439 Author: Steve Date: Fri Oct 1 12:43:55 2021 -0400 initial migration diff --git a/board.go b/board.go new file mode 100644 index 0000000..e288e03 --- /dev/null +++ b/board.go @@ -0,0 +1,155 @@ +package tome_lib + +import ( + "fmt" + "log" +) + +type Board struct { + Sentinal [4]*Card `json:"sentinal"` + Scourge [4]*Card `json:"scourge"` +} + +func (b *Board) String() string { + return fmt.Sprintf("-----------------\n|%v|%v|%v|%v|\n-----------------\n|%v|%v|%v|%v|\n-----------------\n", b.Sentinal[0], b.Sentinal[1], b.Sentinal[2], b.Sentinal[3], b.Scourge[0], b.Scourge[1], b.Scourge[2], b.Scourge[3]) +} + +func (b *Board) GetRow(id int) []*Card { + if id == SentinalID { + return b.Sentinal[:] + } else if id == ScourgeID { + return b.Scourge[:] + } else { + log.Println("asked for invalid row") + return nil + } +} + +func (b *Board) GetCard(id int, pos int) *Card { + return b.GetRow(id)[pos] +} + +func (b *Board) Remove(c *Card) { + for k, v := range b.Sentinal { + if v.Id == c.Id { + b.Sentinal[k] = NewEmpty(k) + } + } + for k, v := range b.Scourge { + if v.Id == c.Id { + b.Scourge[k] = NewEmpty(k) + } + } +} + +func (b *Board) Empty(id int) bool { + res := true + row := b.GetRow(id) + for _, v := range row { + if !v.Empty() { + res = false + } + } + + return res +} + +func (b *Board) CanMove(id, src, dest int) bool { + brd := b.GetRow(id) + if src < 0 || src > 3 || dest < 0 || dest > 3 { + return false + } + if brd[src].Empty() { + return false + } + if !brd[dest].Empty() { + return false + } + if brd[src].Sick { + return false + } + return true +} + +func (b *Board) Move(id, src, dest int) bool { + brd := b.GetRow(id) + brd[dest] = brd[src] + brd[dest].Position = dest + brd[src] = NewEmpty(src) + return true +} + +func (b *Board) CanPlay(id int, c *Card, dest int) bool { + brd := b.GetRow(id) + if dest < 0 || dest > 3 { + return false + } + if !brd[dest].Empty() && !c.Spell { + return false + } + return true +} + +func (b *Board) Play(id int, c *Card, dest int, should bool) bool { + brd := b.GetRow(id) + if should { + c.Position = dest + c.Owner = id + brd[dest] = c + } else { + return false + } + return true +} + +func (b *Board) CanAttack(id, atk, def int) bool { + aBrd := b.GetRow(id) + if atk < 0 || atk > 3 || def < 0 || def > 3 { + return false + } + if aBrd[atk].Empty() || aBrd[atk].Sick || atk != def { + return false + } + return true +} + +func (b *Board) Attack(id, atk, def int) int { + var aid, did int + if id == SentinalID { + aid = SentinalID + did = ScourgeID + } else { + aid = ScourgeID + did = SentinalID + } + attacker := b.GetRow(aid)[atk] + defender := b.GetRow(did)[def] + if defender.Empty() { + //health damage + return 1 + } + //Do actual battle math + atkpower := attacker.Power + defpower := defender.Power + log.Printf("Atk:%v v Def: %v", atkpower, defpower) + if atkpower > defpower { + return 2 + } + if atkpower == defpower { + return 4 + } + if atkpower < defpower { + return 3 + } + return -1 + +} + +func (b *Board) ResetCards() { + for _, v := range b.Sentinal { + v.Power = v.BasePower + } + for _, v := range b.Scourge { + v.Power = v.BasePower + } +} diff --git a/card.go b/card.go new file mode 100644 index 0000000..08efd3d --- /dev/null +++ b/card.go @@ -0,0 +1,70 @@ +package tome_lib + +import ( + "fmt" + + "github.com/google/uuid" +) + +type Card struct { + Type CardType `json:"type"` + BasePower int `json:"base_power"` + Power int `json:"power"` + Id uuid.UUID `json:"id"` + Sick bool `json:"sick"` + Counters int `json:"counters"` + Owner int `json:"owner"` + Position int `json:"position"` + Spell bool `json:"spell"` + Effects []*Effect `json:"effects"` +} + +type CardType int + +const ( + Valk CardType = iota + Ace + Two + Three + Four + Five + Six + Seven + Eight +) +const ( + EmptyValue CardType = -1 +) + +func NewEmpty(p int) *Card { + return &Card{ + Type: EmptyValue, + BasePower: -1, + Power: -1, + Id: uuid.New(), + Sick: false, + Counters: 0, + Owner: -1, + Position: p, + Spell: false, + Effects: []*Effect{}, + } +} +func (c CardType) String() string { + if c == -1 { + return " " + } + return []string{"V", "A", "2", "3", "4", "5", "6", "7", "8"}[c] +} + +func (c *Card) Empty() bool { + return c.Type == EmptyValue +} + +func (c *Card) String() string { + ready := " " + if c.Sick { + ready = "*" + } + return fmt.Sprintf("%v%v%v", c.Type, c.Power, ready) +} diff --git a/cmd.go b/cmd.go new file mode 100644 index 0000000..9d115f9 --- /dev/null +++ b/cmd.go @@ -0,0 +1,34 @@ +package tome_lib + +import "fmt" + +type CmdType string + +const ( + ActCmd = "a" + StateCmd = "s" + DebugCmd = "d" + InvalidCmd = "e" +) + +type Command struct { + PlayerID int `json:"player_id"` + Type CmdType `json:"type"` + Cmd string `json:"cmd"` +} + +func (c *Command) String() string { + return fmt.Sprintf("%v %v %v", c.PlayerID, c.Type, c.Cmd) +} + +type CommandResult struct { + PlayerID int `json:"player_id"` + ResultType CmdType `json:"result_type"` + StateResult *GameView `json:"state_result,omitempty"` + ActionResult *Deck `json:"action_result,omitempty"` + DebugResult *interface{} `json:"debug_result,omitempty"` +} + +func (c *CommandResult) String() string { + return fmt.Sprintf("%v %v\nState Result: %v\nAction Result: %v\nDebug: %v\n", c.PlayerID, c.ResultType, c.StateResult, c.ActionResult, c.DebugResult) +} diff --git a/deck.go b/deck.go new file mode 100644 index 0000000..d3dd16c --- /dev/null +++ b/deck.go @@ -0,0 +1,52 @@ +package tome_lib + +import ( + "fmt" + "math/rand" + "time" +) + +type Deck struct { + Cards []*Card `json:"cards"` +} + +func (d *Deck) String() string { + if d == nil { + return "||" + } + return fmt.Sprintf("|%v|", d.Cards) +} + +func DeckFromCards(c []*Card) *Deck { + return &Deck{ + Cards: c, + } +} + +func (d *Deck) Shuffle() { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + for i := range d.Cards { + j := r.Intn(i + 1) + d.Cards[i], d.Cards[j] = d.Cards[j], d.Cards[i] + } +} + +func (d *Deck) Scry(s int) []*Card { + seen := []*Card{} + if len(d.Cards) < s { + seen = d.Cards + d.Cards = []*Card{} + return seen + } + seen = d.Cards[(len(d.Cards) - s):len(d.Cards)] + d.Cards = d.Cards[0 : len(d.Cards)-s] + return seen +} + +func (d *Deck) Bottom(result []*Card) { + d.Cards = append(result, d.Cards...) //Should shuffle result first? +} + +func (d *Deck) Size() int { + return len(d.Cards) +} diff --git a/effect.go b/effect.go new file mode 100644 index 0000000..7869160 --- /dev/null +++ b/effect.go @@ -0,0 +1,42 @@ +package tome_lib + +import ( + "log" + + "github.com/google/uuid" +) + +type Effect struct { + Owner uuid.UUID + Target uuid.UUID + ID int +} + +func RemoveEffect(source uuid.UUID, c *Card) { + if c.Type == EmptyValue { + return + } + for i, e := range c.Effects { + if e.Owner == source { + c.Effects = append(c.Effects[:i], c.Effects[i+1:]...) + } + } +} + +func AddEffect(c *Card, e *Effect) { + if c.Type == EmptyValue { + log.Println("Can't add effect to empty card") + return + } + if c.Position < 0 { + log.Println("trying to apply effect to card not on the board") + } + for _, v := range c.Effects { + if v.Owner == e.Owner && v.ID == e.ID && v.Target == e.Target { + log.Println("can't stack effects") + return + } + } + log.Printf("applying %v to %v", e, c) + c.Effects = append(c.Effects, e) +} diff --git a/game_view.go b/game_view.go new file mode 100644 index 0000000..4dd6cad --- /dev/null +++ b/game_view.go @@ -0,0 +1,20 @@ +package tome_lib + +import "fmt" + +type GameView struct { + Board *Board `json:"board"` + Player *Player `json:"player"` + DeckSize int `json:"deck_size"` + EnemyLife int `json:"enemy_life"` + EnemyDeckSize int `json:"enemy_deck_size"` + EnemyHandSize int `json:"enemy_hand_size"` + CurrentTurn int `json:"current_turn"` + CanDraw bool `json:"can_draw"` + HasDrawn bool `json:"has_drawn"` + Status GameStatus `json:"game_status"` +} + +func (v *GameView) String() string { + return fmt.Sprintf("Enemy Life: %v Enemy Hand Size: %v Enemy DeckSize: %v\n\n%v\n\n%v\nYou Life: %v\nCT:%v CD: %v, HD %v, Status: %v\n", v.EnemyLife, v.EnemyHandSize, v.EnemyDeckSize, v.Board, v.Player.Hand, v.Player.Life, v.CurrentTurn, v.CanDraw, v.HasDrawn, v.Status) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0ac19fd --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module tome_lib + +go 1.16 + +require github.com/google/uuid v1.3.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..3dfe1c9 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/player.go b/player.go new file mode 100644 index 0000000..e4c62c5 --- /dev/null +++ b/player.go @@ -0,0 +1,19 @@ +package tome_lib + +type Player struct { + Name string `json:"name"` + Id int `json:"id"` + Hand []*Card `json:"hand"` + Life int `json:"life"` + Ready bool `json:"ready"` +} + +func NewPlayer(name string, id int) *Player { + return &Player{ + Name: name, + Id: id, + Hand: []*Card{}, + Life: 3, + Ready: false, + } +} diff --git a/session.go b/session.go new file mode 100644 index 0000000..24b5869 --- /dev/null +++ b/session.go @@ -0,0 +1,64 @@ +package tome_lib + +import ( + "fmt" + + "github.com/google/uuid" +) + +type SessionCmd string +type SessionResp string + +const ( + SessionCmdQuery SessionCmd = "query" + SessionCmdJoin = "join" + SessionCmdLeave = "leave" + SessionCmdPlay = "play" + SessionCmdPoll = "poll" + SessionCmdReady = "ready" +) + +const ( + SessionRespFound SessionResp = "found" + SessionRespJoined1 = "joined p1" + SessionRespJoined2 = "joined p2" + SessionRespReady = "game ready" + SessionRespJoinError = "join error" + SessionRespLeft = "left" + SessionRespPlayed = "played" + SessionRespError = "generic error" + SessionRespBroadcastSenTurn = "Sentinal turn" + SessionRespBroadcastScoTrun = "Scourge turn" + SessionRespBroadcastSenWin = "Sentinal wins" + SessionRespBroadcastScoWin = "Scourge wins" + SessionRespBroadcastUpdate = "update" + SessionRespBroadcastSenJoin = "Sentinal joined" + SessionRespBroadcastScoJoin = "Scourge joined" + SessionRespBroadcastSenReady = "Sentinal player is ready" + SessionRespBroadcastScoReady = "Scourge player is ready" + SessionRespBroadcastSenLeft = "Sentinal player has left" + SessionRespBroadcastScoLeft = "Scourge player has left" + SessionRespBroadcastNone = "" +) + +type SessionCommand struct { + ID uuid.UUID `json:"player_id"` + MatchID uuid.UUID `json:"match_id"` + Command SessionCmd `json:"command"` + GameCommand *Command `json:"game_command,omitempty"` +} + +func (s *SessionCommand) String() string { + return fmt.Sprintf("%v %v %v\n", s.ID, s.Command, s.GameCommand) +} + +type SessionCommandResult struct { + ID uuid.UUID `json:"player_id"` + MatchID uuid.UUID `json:"match_id"` + Result SessionResp `json:"result"` + GameResult *CommandResult `json:"game_result,omitempty"` +} + +func (s *SessionCommandResult) String() string { + return fmt.Sprintf("%v %v %v\n", s.ID, s.Result, s.GameResult) +} diff --git a/util.go b/util.go new file mode 100644 index 0000000..2adec51 --- /dev/null +++ b/util.go @@ -0,0 +1,18 @@ +package tome_lib + +type GameStatus int + +const ( + StatusLobby = iota + StatusReady + StatusPlaying + StatusStop + StatusSentinalWin + StatusScourgeWin + StatusDraw +) + +const ( + SentinalID = 1 + ScourgeID = 2 +)