commit a51bfc6ae8a18f18cc6f67224eadee95a3f979ac Author: Steve Date: Thu Jul 15 19:26:57 2021 -0400 initial work, action moves set diff --git a/board.go b/board.go new file mode 100644 index 0000000..fb3b0de --- /dev/null +++ b/board.go @@ -0,0 +1,161 @@ +package main + +type Board struct { + Sentinal [4]Card + SenBuf [4]bool + Scourge [4]Card + ScoBuf [4]bool +} + +func NewBoard() *Board { + return &Board{ + Sentinal: [4]Card{-1, -1, -1, -1}, + SenBuf: [4]bool{true, true, true, true}, + Scourge: [4]Card{-1, -1, -1, -1}, + ScoBuf: [4]bool{true, true, true, true}, + } +} + +func (b *Board) GetRow(id int) []Card { + if id == 1 { + return b.Sentinal[:] + } else { + return b.Scourge[:] + } +} + +func (b *Board) Move(id, src, dest int) bool { + var brd [4]Card + if id == 1 { + brd = b.Sentinal + } else { + brd = b.Scourge + } + if brd[src] == -1 { + return false + } + if brd[dest] != -1 { + return false + } + brd[dest] = brd[src] + brd[src] = -1 + if id == 1 { + b.Sentinal = brd + b.SenBuf[dest] = false + } else { + b.Scourge = brd + b.ScoBuf[dest] = false + } + return true +} + +func (b *Board) Play(id int, c Card, dest int) bool { + var brd [4]Card + if id == 1 { + brd = b.Sentinal + } else { + brd = b.Scourge + } + if brd[dest] != -1 { + return false + } + brd[dest] = c + if id == 1 { + b.Sentinal = brd + b.SenBuf[dest] = false + } else { + b.Scourge = brd + b.ScoBuf[dest] = false + } + return true +} + +func (b *Board) Attack(id int, atk, def int) int { + var aBrd [4]Card + var dBrd [4]Card + var aBuf [4]bool + var dBuf [4]bool + if id == 1 { + aBrd = b.Sentinal + aBuf = b.SenBuf + dBrd = b.Scourge + dBuf = b.ScoBuf + } else { + aBrd = b.Scourge + aBuf = b.ScoBuf + dBrd = b.Sentinal + dBuf = b.SenBuf + } + if aBrd[atk] == -1 || !aBuf[atk] || !aBrd[atk].CanAttack(atk, def) { + return -1 + } + aBuf[atk] = false + if dBrd[def] == -1 { + //health damage + if id == 1 { + b.Sentinal = aBrd + b.SenBuf = aBuf + b.Scourge = dBrd + b.ScoBuf = dBuf + } else { + b.Scourge = aBrd + b.ScoBuf = aBuf + b.Sentinal = dBrd + b.SenBuf = dBuf + } + return 1 + } + //Do actual battle math + attacker := aBrd[atk] + defender := dBrd[def] + //check atk buffs + for i, v := range aBrd { + if v == Two { + attacker = attacker + 1 + } + if v == Three && (i == atk-1 || i == atk+1) { + attacker = attacker + 1 + } + } + for i, v := range dBrd { + if v == Two { + defender = defender + 1 + } + if v == Three && (i == def-1 || i == def+1) { + defender = defender + 1 + } + } + if attacker > defender { + dBrd[def] = -1 + if id == 1 { + b.Sentinal = aBrd + b.SenBuf = aBuf + b.Scourge = dBrd + b.ScoBuf = dBuf + } else { + b.Scourge = aBrd + b.ScoBuf = aBuf + b.Sentinal = dBrd + b.SenBuf = dBuf + } + return 0 + } + if attacker == defender { + aBrd[atk] = -1 + dBrd[def] = -1 + if id == 1 { + b.Sentinal = aBrd + b.SenBuf = aBuf + b.Scourge = dBrd + b.ScoBuf = dBuf + } else { + b.Scourge = aBrd + b.ScoBuf = aBuf + b.Sentinal = dBrd + b.SenBuf = dBuf + } + return 0 + } + return -1 + +} diff --git a/card.go b/card.go new file mode 100644 index 0000000..296d953 --- /dev/null +++ b/card.go @@ -0,0 +1,31 @@ +package main + +type Card int + +const ( + Valk Card = iota + Ace + Two + Three + Four + Five + Six + Seven + Eight + Nine + Ten + Jack + Queen + King +) + +func (c Card) String() string { + return []string{"V", "A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"}[c] +} + +func (c Card) CanAttack(src, dest int) bool { + if c == Eight || src != dest { + return false + } + return true +} diff --git a/deck.go b/deck.go new file mode 100644 index 0000000..a8f0c05 --- /dev/null +++ b/deck.go @@ -0,0 +1,44 @@ +package main + +import "math/rand" + +type Deck struct { + Cards []Card +} + +func NewDeck() *Deck { + cards := []Card{Valk} + for i := 0; i < 3; i++ { + for j := 1; j < 14; j++ { + cards = append(cards, Card(j)) + } + } + return &Deck{ + Cards: cards, + } +} + +func (d *Deck) Shuffle() { + cards := d.Cards + for i := range cards { + j := rand.Intn(i + 1) + cards[i], cards[j] = cards[j], cards[i] + } + d.Cards = cards +} + +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? +} diff --git a/game.go b/game.go new file mode 100644 index 0000000..de95001 --- /dev/null +++ b/game.go @@ -0,0 +1,131 @@ +package main + +import ( + "strconv" + "strings" +) + +type Game struct { + GameBoard *Board + SentinalPlayer *Player + ScourgePlayer *Player + SentinalDeck *Deck + ScourgeDeck *Deck + CurrentTurn int + CardBuffer []Card + CanDraw bool +} + +func NewGame() *Game { + deckA := NewDeck() + deckB := NewDeck() + deckA.Shuffle() + deckB.Shuffle() + return &Game{ + GameBoard: NewBoard(), + SentinalPlayer: NewPlayer("Sentinal", 1), + ScourgePlayer: NewPlayer("Scourge", 2), + SentinalDeck: deckA, + ScourgeDeck: deckB, + CurrentTurn: 0, //start with no turn + CardBuffer: []Card{}, + CanDraw: false, + } +} + +func (g *Game) PlayerAct(id int, cmd string) []Card { + if id != g.CurrentTurn { + return nil + } + var curr *Player + var opp *Player + var currD *Deck + if id == g.SentinalPlayer.Id { + curr = g.SentinalPlayer + opp = g.ScourgePlayer + currD = g.SentinalDeck + } else { + curr = g.ScourgePlayer + opp = g.SentinalPlayer + currD = g.ScourgeDeck + } + cmd_s := strings.Split(cmd, " ") + if len(cmd_s) < 1 { + return nil + } + switch cmd_s[0] { + case "s": + //scry: return scry options off top of deck + g.CardBuffer = currD.Scry(curr.Life) + return g.CardBuffer + case "d": + //draw: return player hand + if len(cmd_s) != 2 { + return nil + } + x_i, err := strconv.Atoi(cmd_s[1]) + if err != nil { + panic(err) + } + x := Card(x_i) + buf := g.CardBuffer + for i, v := range buf { + if v == x { + buf = append(buf[:i], buf[i+1:]...) + } + } + currD.Bottom(buf) + return []Card{x} + + case "m": + //move: return player board or [] if invalid + if len(cmd_s) != 3 { + return nil + } + x_i, _ := strconv.Atoi(cmd_s[1]) + y_i, _ := strconv.Atoi(cmd_s[2]) + res := g.GameBoard.Move(g.CurrentTurn, x_i, y_i) + if res { + return g.GameBoard.GetRow(g.CurrentTurn) + } else { + return []Card{} + } + case "a": + //attack + if len(cmd_s) != 3 { + return nil + } + x_i, _ := strconv.Atoi(cmd_s[1]) + y_i, _ := strconv.Atoi(cmd_s[2]) + res := g.GameBoard.Attack(g.CurrentTurn, x_i, y_i) + if res == 1 { + opp.Life = opp.Life - 1 + return g.GameBoard.GetRow(g.CurrentTurn) + } else if res == 0 { + return g.GameBoard.GetRow(g.CurrentTurn) + } else { + return []Card{} + } + case "p": + //play: return player boad or [] if invalid + if len(cmd_s) != 2 { + return nil + } + x_i, _ := strconv.Atoi(cmd_s[1]) + y_i, _ := strconv.Atoi(cmd_s[2]) + res := g.GameBoard.Play(g.CurrentTurn, Card(x_i), y_i) + if res { + for i, v := range curr.Hand { + if v == Card(x_i) { + curr.Hand = append(curr.Hand[:i], curr.Hand[i+1:]...) + } + } + return g.GameBoard.GetRow(g.CurrentTurn) + } else { + return []Card{} + } + default: + return nil + } + return nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..220d3b3 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module snengame + +go 1.16 diff --git a/main.go b/main.go new file mode 100644 index 0000000..7905807 --- /dev/null +++ b/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + +} diff --git a/player.go b/player.go new file mode 100644 index 0000000..edc64b0 --- /dev/null +++ b/player.go @@ -0,0 +1,17 @@ +package main + +type Player struct { + Name string + Id int + Hand []Card + Life int +} + +func NewPlayer(name string, id int) *Player { + return &Player{ + Name: name, + Id: id, + Hand: []Card{}, + Life: 3, + } +}