move to effect based system

This commit is contained in:
stryan 2021-07-25 15:33:47 -04:00
parent a623639af3
commit 26a7c137f8
5 changed files with 174 additions and 124 deletions

View File

@ -2,6 +2,7 @@ package game
import (
"fmt"
"log"
)
type Board struct {
@ -17,7 +18,7 @@ func NewBoard() *Board {
}
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])
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 {
@ -59,6 +60,9 @@ func (b *Board) Empty(id int) bool {
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
}
@ -72,33 +76,17 @@ func (b *Board) CanMove(id, src, dest int) bool {
}
func (b *Board) Move(id, src, dest int) bool {
var brd [4]*Card
if id == SentinalID {
brd = b.Sentinal
} else {
brd = b.Scourge
}
if brd[src].Empty() {
return false
}
if !brd[dest].Empty() {
return false
}
if brd[src].Sick {
return false
}
brd := b.GetRow(id)
brd[dest] = brd[src]
brd[src] = NewEmpty(src)
if id == SentinalID {
b.Sentinal = brd
} else {
b.Scourge = brd
}
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
}
@ -118,59 +106,52 @@ func (b *Board) Play(id int, c *Card, dest int, should bool) bool {
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 int, atk, def int) int {
var aBrd [4]*Card
var dBrd [4]*Card
func (b *Board) Attack(id, atk, def int) int {
var aid, did int
if id == SentinalID {
aBrd = b.Sentinal
dBrd = b.Scourge
aid = SentinalID
did = ScourgeID
} else {
aBrd = b.Scourge
dBrd = b.Sentinal
aid = ScourgeID
did = SentinalID
}
if dBrd[def].Empty() {
attacker := b.GetRow(aid)[atk]
defender := b.GetRow(did)[def]
if defender.Empty() {
//health damage
if id == SentinalID {
b.Sentinal = aBrd
b.Scourge = dBrd
} else {
b.Scourge = aBrd
b.Sentinal = dBrd
}
return 1
}
//Do actual battle math
attacker := aBrd[atk].Power
defender := dBrd[def].Power
if attacker > defender {
dBrd[def] = NewEmpty(def)
if id == SentinalID {
b.Sentinal = aBrd
b.Scourge = dBrd
} else {
b.Scourge = aBrd
b.Sentinal = dBrd
atkpower := attacker.Power
defpower := defender.Power
log.Printf("Atk:%v v Def: %v", atkpower, defpower)
if atkpower > defpower {
return 2
}
return 0
if atkpower == defpower {
return 4
}
if attacker == defender {
aBrd[atk] = NewEmpty(atk)
dBrd[def] = NewEmpty(def)
if id == 1 {
b.Sentinal = aBrd
b.Scourge = dBrd
} else {
b.Scourge = aBrd
b.Sentinal = dBrd
}
return 0
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
}
}

View File

@ -16,6 +16,7 @@ type Card struct {
Owner int `json:"owner"`
Position int `json:"position"`
Spell bool `json:"spell"`
Effects []Effect `json:"effects"`
}
type CardType int
@ -56,6 +57,7 @@ func NewCard(v, o, p int, id uuid.UUID) *Card {
Owner: o,
Position: p,
Spell: OracleSpell(CardType(v), nil),
Effects: []Effect{},
}
}
@ -69,6 +71,8 @@ func NewEmpty(p int) *Card {
Counters: 0,
Owner: -1,
Position: p,
Spell: false,
Effects: []Effect{},
}
}
@ -77,5 +81,9 @@ func (c *Card) Empty() bool {
}
func (c *Card) String() string {
return fmt.Sprintf("|%v|", c.Type)
ready := " "
if c.Sick {
ready = "*"
}
return fmt.Sprintf("%v%v%v", c.Type, c.Power, ready)
}

26
internal/game/effect.go Normal file
View File

@ -0,0 +1,26 @@
package game
import "github.com/google/uuid"
type Effect struct {
Owner uuid.UUID
Target uuid.UUID
ID int
}
func RemoveEffect(source uuid.UUID, c *Card) {
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) {
for _, v := range c.Effects {
if v.Owner == e.Owner && v.ID == e.ID {
return
}
}
c.Effects = append(c.Effects, e)
}

View File

@ -125,6 +125,16 @@ func (g *Game) StateChanges() {
g.Status = StatusSentinalWin
}
}
//reapply card effects
g.GameBoard.ResetCards()
for _, v := range g.GameBoard.Sentinal {
OracleTick(v, g) //apply effect stacks first
OracleEffect(v, g) //actually activate effects
}
for _, v := range g.GameBoard.Scourge {
OracleTick(v, g)
OracleEffect(v, g)
}
//check life
//this is second on purpose so that it shadows deck out win conditions
//if you use your last action to win the game, you should actually win
@ -222,10 +232,12 @@ func (g *Game) PlayerAct(id int, cmd string) *Deck {
switch cmd_s[0] {
case "s":
//scry: return scry options off top of deck
if !g.CanDraw || g.CardBuffer.Size() > 0 {
if !g.CanDraw {
return nil
}
if g.CardBuffer.Size() <= 0 {
g.CardBuffer = DeckFromCards(currD.Scry(curr.Life))
}
return g.CardBuffer
case "d":
//draw: return player hand
@ -236,6 +248,9 @@ func (g *Game) PlayerAct(id int, cmd string) *Deck {
return nil
}
x_i, err := strconv.Atoi(cmd_s[1])
if x_i > 2 || x_i < 0 {
return nil
}
if err != nil {
panic(err)
}
@ -282,12 +297,34 @@ func (g *Game) PlayerAct(id int, cmd string) *Deck {
if g.GameBoard.CanAttack(g.CurrentTurn, x_i, y_i) {
OracleAttack(g.GameBoard.GetCard(g.CurrentTurn, x_i), g)
res := g.GameBoard.Attack(g.CurrentTurn, x_i, y_i)
if res == 1 {
opp.Life = opp.Life - 1
return DeckFromCards(g.GameBoard.GetRow(g.CurrentTurn))
var aid, did int
if id == SentinalID {
aid = SentinalID
did = ScourgeID
} else {
return DeckFromCards(g.GameBoard.GetRow(g.CurrentTurn))
aid = ScourgeID
did = SentinalID
}
attacker := g.GameBoard.GetRow(aid)[x_i]
defender := g.GameBoard.GetRow(did)[y_i]
switch res {
case 1:
opp.Life = opp.Life - 1
case 2:
OracleLeaves(defender, g)
g.GameBoard.Remove(defender)
case 3:
OracleLeaves(attacker, g)
g.GameBoard.Remove(attacker)
case 4:
OracleLeaves(attacker, g)
OracleLeaves(defender, g)
g.GameBoard.Remove(attacker)
g.GameBoard.Remove(defender)
}
return DeckFromCards(g.GameBoard.GetRow(g.CurrentTurn))
} else {
log.Println("can't attack")
return DeckFromCards([]*Card{})
@ -306,10 +343,10 @@ func (g *Game) PlayerAct(id int, cmd string) *Deck {
card := curr.Hand[x_i]
shouldPlace := true
if g.GameBoard.CanPlay(g.CurrentTurn, card, y_i) {
shouldPlace = OracleCast(curr.Hand[x_i], g)
shouldPlace = OracleCast(card, g)
placed := g.GameBoard.Play(g.CurrentTurn, card, y_i, shouldPlace)
if placed {
OracleEnters(curr.Hand[x_i], g)
OracleEnters(card, g)
}
curr.Hand = append(curr.Hand[:x_i], curr.Hand[x_i+1:]...)
return DeckFromCards(g.GameBoard.GetRow(g.CurrentTurn))

View File

@ -1,7 +1,5 @@
package game
import "log"
func OracleUpkeep(c *Card, g *Game) {
switch c.Type {
case Eight:
@ -39,79 +37,59 @@ func OracleEnters(c *Card, g *Game) {
switch c.Type {
case Ace:
c.Sick = false
return
case Four:
AddEffect(c, Effect{c.Id, c.Id, 2})
case Eight:
c.Counters = 0
}
}
func OracleTick(c *Card, g *Game) {
row := g.GameBoard.GetRow(c.Owner)
switch c.Type {
case Two:
//+1 to all
if c.Owner == SentinalID {
for _, v := range g.GameBoard.Sentinal {
v.Power = v.Power + 1
for _, v := range row {
if v.Id != c.Id {
v.Effects = append(v.Effects, Effect{c.Id, v.Id, 1})
AddEffect(v, Effect{c.Id, v.Id, 1})
}
} else if c.Owner == ScourgeID {
for _, v := range g.GameBoard.Scourge {
v.Power = v.Power + 1
}
} else {
log.Println("Trying to lookup an ETB when card not on field")
}
case Three:
//+1 around it
if c.Owner == SentinalID {
if c.Position-1 >= 0 {
g.GameBoard.Sentinal[c.Position-1].Power = g.GameBoard.Sentinal[c.Position-1].Power + 1
}
if c.Position+1 <= 3 {
g.GameBoard.Sentinal[c.Position+1].Power = g.GameBoard.Sentinal[c.Position+1].Power + 1
}
v := row[c.Position-1]
AddEffect(v, Effect{c.Id, v.Id, 1})
}
if c.Owner == ScourgeID {
if c.Position-1 >= 0 {
g.GameBoard.Scourge[c.Position-1].Power = g.GameBoard.Scourge[c.Position-1].Power + 1
}
if c.Position+1 <= 3 {
g.GameBoard.Scourge[c.Position+1].Power = g.GameBoard.Scourge[c.Position+1].Power + 1
}
v := row[c.Position+1]
AddEffect(v, Effect{c.Id, v.Id, 1})
}
}
return
}
func OracleLeaves(c *Card, g *Game) {
row := g.GameBoard.GetRow(c.Owner)
switch c.Type {
case Two:
//remove +1 to all
if c.Owner == SentinalID {
for _, v := range g.GameBoard.Sentinal {
v.Power = v.Power - 1
}
} else if c.Owner == ScourgeID {
for _, v := range g.GameBoard.Scourge {
v.Power = v.Power - 1
}
} else {
log.Println("Trying to lookup an LTB when card not on field")
for _, v := range row {
RemoveEffect(c.Id, v)
}
case Three:
//+1 around it
if c.Owner == SentinalID {
if c.Position-1 >= 0 {
g.GameBoard.Sentinal[c.Position-1].Power = g.GameBoard.Sentinal[c.Position-1].Power - 1
RemoveEffect(c.Id, row[c.Position-1])
}
if c.Position+1 <= 3 {
g.GameBoard.Sentinal[c.Position+1].Power = g.GameBoard.Sentinal[c.Position+1].Power - 1
RemoveEffect(c.Id, row[c.Position+1])
}
}
if c.Owner == ScourgeID {
if c.Position-1 >= 0 {
g.GameBoard.Scourge[c.Position-1].Power = g.GameBoard.Scourge[c.Position-1].Power - 1
}
if c.Position+1 <= 3 {
g.GameBoard.Scourge[c.Position+1].Power = g.GameBoard.Scourge[c.Position+1].Power - 1
}
}
}
return
}
@ -132,13 +110,33 @@ func OracleMove(c *Card, src, dest int, g *Game) {
switch c.Type {
case Three:
row := g.GameBoard.GetRow(c.Owner)
row[src-1].Power = row[src-1].Power - 1
row[src+1].Power = row[src+1].Power - 1
row[dest-1].Power = row[dest-1].Power + 1
row[dest+1].Power = row[dest+1].Power + 1
if src-1 >= 0 {
RemoveEffect(c.Id, row[src-1])
}
if src+1 <= 3 {
RemoveEffect(c.Id, row[src-1])
}
}
}
func OracleAttack(c *Card, g *Game) {
c.Sick = true
}
func OracleEffect(c *Card, g *Game) {
for _, e := range c.Effects {
switch e.ID {
case 1:
c.Power = c.Power + 1
case 2:
if c.Owner == SentinalID {
g.CardBuffer = DeckFromCards(g.SentinalDeck.Scry(1))
} else {
g.CardBuffer = DeckFromCards(g.SentinalDeck.Scry(1))
}
g.CanDraw = true
g.HasDrawn = false
RemoveEffect(e.Owner, c)
}
}
}