Added take trick action
Removed ready commands too since it was a small change
Change-Id: I3f20b46f2d78262ff7573d80a42f9a7825bee9f9
diff --git a/go/src/hearts/assets/TakeTrickHandPressed.png b/go/src/hearts/assets/TakeTrickHandPressed.png
new file mode 100644
index 0000000..b6fc11e
--- /dev/null
+++ b/go/src/hearts/assets/TakeTrickHandPressed.png
Binary files differ
diff --git a/go/src/hearts/assets/TakeTrickHandUnpressed.png b/go/src/hearts/assets/TakeTrickHandUnpressed.png
new file mode 100644
index 0000000..ae111ad
--- /dev/null
+++ b/go/src/hearts/assets/TakeTrickHandUnpressed.png
Binary files differ
diff --git a/go/src/hearts/assets/TakeTrickTablePressed.png b/go/src/hearts/assets/TakeTrickTablePressed.png
new file mode 100644
index 0000000..3a62b9b
--- /dev/null
+++ b/go/src/hearts/assets/TakeTrickTablePressed.png
Binary files differ
diff --git a/go/src/hearts/assets/TakeTrickTableUnpressed.png b/go/src/hearts/assets/TakeTrickTableUnpressed.png
new file mode 100644
index 0000000..bb9078a
--- /dev/null
+++ b/go/src/hearts/assets/TakeTrickTableUnpressed.png
Binary files differ
diff --git a/go/src/hearts/img/img_test.go b/go/src/hearts/img/img_test.go
index e3a49b8..b80115a 100644
--- a/go/src/hearts/img/img_test.go
+++ b/go/src/hearts/img/img_test.go
@@ -84,12 +84,12 @@
})
imgPos := coords.MakeVec(5, 20)
imgDimensions := coords.MakeVec(10, 10)
- newButton := texture.MakeImgWithoutAlt(subtex, imgPos, imgDimensions, u.Eng, u.Scene)
- u.Buttons = append(u.Buttons, newButton)
+ newButton := texture.MakeImgWithoutAlt(subtex, imgPos, imgDimensions, u)
+ u.Buttons["1"] = newButton
oldWindow := u.WindowSize.DividedBy(2)
resize.AdjustImgs(oldWindow, u)
- newPos := u.Buttons[0].GetCurrent()
- newDimensions := u.Buttons[0].GetDimensions()
+ newPos := u.Buttons["1"].GetCurrent()
+ newDimensions := u.Buttons["1"].GetDimensions()
dimExpect := imgDimensions.Times(2)
posExpect := imgPos.Times(2)
if newDimensions.X != dimExpect.X {
@@ -110,9 +110,11 @@
func TestFour(test *testing.T) {
scene := &sprite.Node{}
eng := glsprite.Engine(nil)
+ u.Eng = eng
+ u.Scene = scene
pos := coords.MakeVec(5, 10)
dimensions := coords.MakeVec(20, 10)
- i := texture.MakeImgWithoutAlt(subtex, pos, dimensions, eng, scene)
+ i := texture.MakeImgWithoutAlt(subtex, pos, dimensions, u)
if i.GetCurrent().X != pos.X {
test.Errorf("Expected x %f, got %f", pos.X, i.GetCurrent().X)
}
@@ -137,9 +139,11 @@
func TestFive(test *testing.T) {
scene := &sprite.Node{}
eng := glsprite.Engine(nil)
+ u.Eng = eng
+ u.Scene = scene
pos := coords.MakeVec(5, 10)
dimensions := coords.MakeVec(20, 10)
- i := texture.MakeImgWithAlt(subtex, subtex, pos, dimensions, true, eng, scene)
+ i := texture.MakeImgWithAlt(subtex, subtex, pos, dimensions, true, u)
if i.GetCurrent().X != pos.X {
test.Errorf("Expected x %f, got %f", pos.X, i.GetCurrent().X)
}
@@ -172,7 +176,7 @@
})
u.EmptySuitImgs = []*staticimg.StaticImg{staticimg.MakeStaticImg(), staticimg.MakeStaticImg(), staticimg.MakeStaticImg(), staticimg.MakeStaticImg()}
u.WindowSize = windowSize
- n := texture.MakeNode(u.Eng, u.Scene)
+ n := texture.MakeNode(u)
for _, e := range u.EmptySuitImgs {
e.SetImage(subtex)
e.SetAlt(subtex)
@@ -180,8 +184,8 @@
}
c := card.NewCard(card.Two, card.Heart)
c2 := card.NewCard(card.Four, card.Heart)
- n = texture.MakeNode(u.Eng, u.Scene)
- n2 := texture.MakeNode(u.Eng, u.Scene)
+ n = texture.MakeNode(u)
+ n2 := texture.MakeNode(u)
initialXY := coords.MakeVec(10, 10)
curXY := coords.MakeVec(100, 30)
dimensions := coords.MakeVec(5, 5)
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index 0e7a6e5..74d92df 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -239,10 +239,10 @@
for counter, i := range imgs {
dims := i.GetDimensions()
to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y-u.WindowSize.Y)
- if counter == len(imgs)-1 {
- animateImageMovement(ch, i, to, dims, u)
- } else {
+ if counter < len(imgs)-1 {
AnimateImageNoChannel(i, to, dims, u)
+ } else {
+ animateImageMovement(ch, i, to, dims, u)
}
}
@@ -285,6 +285,7 @@
bannerImgs = append(bannerImgs, u.Other...)
bannerImgs = append(bannerImgs, u.Buttons["toggleSplit"])
tableImgs = append(tableImgs, u.DropTargets...)
+ tableImgs = append(tableImgs, u.Buttons["takeTrick"])
tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers]...)
for _, img := range tableImgs {
from := img.GetCurrent()
@@ -323,6 +324,7 @@
bannerImgs = append(bannerImgs, u.Other...)
bannerImgs = append(bannerImgs, u.Buttons["toggleSplit"])
tableImgs = append(tableImgs, u.DropTargets...)
+ tableImgs = append(tableImgs, u.Buttons["takeTrick"])
tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers]...)
for _, img := range tableImgs {
from := img.GetCurrent()
@@ -373,7 +375,6 @@
// Animation for when a trick is taken, when app is in the table view
func AnimateTableCardTakeTrick(cards []*card.Card, dir direction.Direction, quit chan bool, u *uistate.UIState) {
- <-time.After(2 * time.Second)
for _, c := range cards {
BringNodeToFront(c.GetNode(), u)
}
@@ -572,6 +573,7 @@
case <-quitChan:
RemoveAnimChan(quitChan, u)
f()
+ <-time.After(time.Second)
return
case <-animChan:
RemoveAnimChan(quitChan, u)
diff --git a/go/src/hearts/img/texture/texture.go b/go/src/hearts/img/texture/texture.go
index aacf862..6b6cd08 100644
--- a/go/src/hearts/img/texture/texture.go
+++ b/go/src/hearts/img/texture/texture.go
@@ -276,7 +276,8 @@
"SitSpotPressed.png", "SitSpotUnpressed.png", "WatchSpotPressed.png", "WatchSpotUnpressed.png", "StartBlue.png", "StartGray.png",
"StartBluePressed.png", "Restart.png", "Visibility.png", "VisibilityOff.png", "QuitPressed.png", "QuitUnpressed.png",
"PassPressed.png", "PassUnpressed.png", "RightArrowBlue.png", "LeftArrowBlue.png", "AcrossArrowBlue.png", "RightArrowGray.png",
- "LeftArrowGray.png", "AcrossArrowGray.png",
+ "LeftArrowGray.png", "AcrossArrowGray.png", "TakeTrickTableUnpressed.png", "TakeTrickTablePressed.png", "TakeTrickHandPressed.png",
+ "TakeTrickHandUnpressed.png",
}
for _, f := range boundedImgs {
a, err := asset.Open(f)
diff --git a/go/src/hearts/img/uistate/uistate.go b/go/src/hearts/img/uistate/uistate.go
index cbdb649..bb5c898 100644
--- a/go/src/hearts/img/uistate/uistate.go
+++ b/go/src/hearts/img/uistate/uistate.go
@@ -134,7 +134,7 @@
Padding: float32(5),
CurView: None,
Done: false,
- Debug: true,
+ Debug: false,
SequentialPhases: true,
SwitchingViews: false,
UserData: make(map[int]map[string]interface{}),
diff --git a/go/src/hearts/img/view/view.go b/go/src/hearts/img/view/view.go
index fcd4814..b7397d2 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -12,7 +12,6 @@
"fmt"
"sort"
"strconv"
- "time"
"hearts/img/coords"
"hearts/img/direction"
@@ -28,10 +27,7 @@
// Arrange view: For seating players
func LoadArrangeView(u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Arrange
@@ -76,10 +72,7 @@
// Waiting view: Displays the word "Waiting". To be displayed when players are waiting for a new round to be dealt
// TODO(emshack): Integrate this with Arrange view and Score view so that a separate screen is not necessary
func LoadWaitingView(u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
center := u.WindowSize.DividedBy(2)
@@ -93,10 +86,7 @@
// Discovery view: Displays a menu of possible games to join
func LoadDiscoveryView(u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Discovery
@@ -140,10 +130,7 @@
// Table View: Displays the table. Intended for public devices
func LoadTableView(u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Table
@@ -154,15 +141,20 @@
dropTargetAlt := u.Texs["trickDropBlue.png"]
dropTargetDimensions := u.CardDim
dropTargetX := (u.WindowSize.X - u.CardDim.X) / 2
- var dropTargetY float32
- if u.WindowSize.X < u.WindowSize.Y {
- dropTargetY = u.WindowSize.Y/2 + u.CardDim.Y/2 + u.Padding
- } else {
- dropTargetY = u.WindowSize.Y/2 + u.Padding
- }
+ dropTargetY := u.WindowSize.Y/2 + u.CardDim.Y/2 + u.Padding
dropTargetPos := coords.MakeVec(dropTargetX, dropTargetY)
u.DropTargets = append(u.DropTargets,
texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u))
+ // take trick button
+ takeTrickImage := u.Texs["TakeTrickTableUnpressed.png"]
+ takeTrickAlt := u.Texs["TakeTrickTablePressed.png"]
+ takeTrickDim := coords.MakeVec(u.CardDim.X, u.CardDim.Y)
+ takeTrickPos := coords.MakeVec(dropTargetX, dropTargetY-u.Padding-takeTrickDim.Y)
+ u.Buttons["takeTrick"] = texture.MakeImgWithAlt(takeTrickImage, takeTrickAlt, takeTrickPos, takeTrickDim, true, u)
+ if !u.CurTable.TrickOver() {
+ var emptyTex sprite.SubTex
+ u.Eng.SetSubTex(u.Buttons["takeTrick"].GetNode(), emptyTex)
+ }
// card on top of first drop target
dropCard := u.CurTable.GetTrick()[0]
if dropCard != nil {
@@ -173,11 +165,7 @@
}
// second drop target
dropTargetY = (u.WindowSize.Y - u.CardDim.Y) / 2
- if u.WindowSize.X < u.WindowSize.Y {
- dropTargetX = u.WindowSize.X/2 - u.CardDim.X - u.Padding
- } else {
- dropTargetX = u.WindowSize.X/2 - 3*u.CardDim.X/2 - u.Padding
- }
+ dropTargetX = u.WindowSize.X/2 - 3*u.CardDim.X/2 - u.Padding
dropTargetPos = coords.MakeVec(dropTargetX, dropTargetY)
u.DropTargets = append(u.DropTargets,
texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u))
@@ -191,11 +179,7 @@
}
// third drop target
dropTargetX = (u.WindowSize.X - u.CardDim.X) / 2
- if u.WindowSize.X < u.WindowSize.Y {
- dropTargetY = u.WindowSize.Y/2 - 3*u.CardDim.Y/2 - u.Padding
- } else {
- dropTargetY = u.WindowSize.Y/2 - u.Padding - u.CardDim.Y
- }
+ dropTargetY = u.WindowSize.Y/2 - 3*u.CardDim.Y/2 - u.Padding
dropTargetPos = coords.MakeVec(dropTargetX, dropTargetY)
u.DropTargets = append(u.DropTargets,
texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u))
@@ -209,11 +193,7 @@
}
// fourth drop target
dropTargetY = (u.WindowSize.Y - u.CardDim.Y) / 2
- if u.WindowSize.X < u.WindowSize.Y {
- dropTargetX = u.WindowSize.X/2 + u.Padding
- } else {
- dropTargetX = u.WindowSize.X/2 + u.CardDim.X/2 + u.Padding
- }
+ dropTargetX = u.WindowSize.X/2 + u.CardDim.X/2 + u.Padding
dropTargetPos = coords.MakeVec(dropTargetX, dropTargetY)
u.DropTargets = append(u.DropTargets,
texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u))
@@ -382,10 +362,7 @@
// Score View: Shows current player standings at the end of every round, including the end of the game
func LoadScoreView(roundScores, winners []int, u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Score
@@ -397,10 +374,7 @@
// Pass View: Shows player's hand and allows them to pass cards
func LoadPassView(u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Pass
@@ -416,10 +390,7 @@
// Take View: Shows player's hand and allows them to take the cards that have been passed to them
func LoadTakeView(u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Take
@@ -436,10 +407,7 @@
// Play View: Shows player's hand and allows them to play cards
func LoadPlayView(u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Play
@@ -463,10 +431,7 @@
}
func LoadSplitView(reloading bool, u *uistate.UIState) {
- if len(u.AnimChans) > 0 {
- reposition.ResetAnims(u)
- <-time.After(time.Second)
- }
+ reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Split
@@ -652,7 +617,16 @@
var turnText string
playerTurnNum := u.CurTable.WhoseTurn()
if playerTurnNum == -1 || !u.CurTable.AllDonePassing() || (u.SequentialPhases && !u.CurTable.AllDoneTaking()) {
- turnText = "Waiting for other players"
+ if u.CurTable.TrickOver() {
+ recipient := u.CurTable.GetTrickRecipient()
+ if recipient == u.CurPlayerIndex {
+ turnText = "Please take your trick"
+ } else {
+ turnText = fmt.Sprintf("Waiting for %s to take the trick", uistate.GetName(recipient, u))
+ }
+ } else {
+ turnText = "Waiting for other players"
+ }
} else if playerTurnNum == u.CurPlayerIndex {
turnText = "Your turn"
} else {
@@ -699,6 +673,16 @@
maxWidth := u.WindowSize.X - pullTabDim.X*2 - u.Padding*4
u.Other = append(u.Other,
texture.MakeStringImgCenterAlign(message, color, color, true, center, scaler, maxWidth, u)...)
+ takeTrickImage := u.Texs["TakeTrickHandUnpressed.png"]
+ takeTrickAlt := u.Texs["TakeTrickHandPressed.png"]
+ takeTrickDim := coords.MakeVec(u.CardDim.X, u.CardDim.Y/2)
+ takeTrickPos := coords.MakeVec(u.Padding, headerPos.Y-takeTrickDim.Y-u.Padding)
+ display := (u.CurTable.TrickOver() && u.CurTable.GetTrickRecipient() == u.CurPlayerIndex)
+ u.Buttons["takeTrick"] = texture.MakeImgWithAlt(takeTrickImage, takeTrickAlt, takeTrickPos, takeTrickDim, true, u)
+ if !display {
+ var emptyTex sprite.SubTex
+ u.Eng.SetSubTex(u.Buttons["takeTrick"].GetNode(), emptyTex)
+ }
}
func addPlaySlot(u *uistate.UIState) {
@@ -956,7 +940,7 @@
tLeft := coords.MakeVec(dropTargetPos.X+dropTargetDimensions.X+2, dropTargetPos.Y)
textImgs = texture.MakeStringImgLeftAlign(strconv.Itoa(numTricks)+trickText, "", "", true, tLeft, scaler, tMax, u)
} else {
- tCenter := coords.MakeVec(dropTargetPos.X+dropTargetDimensions.X/2, dropTargetPos.Y-u.Padding-10)
+ tCenter := coords.MakeVec(dropTargetPos.X+dropTargetDimensions.X/2, dropTargetPos.Y-u.Padding-15)
textImgs = texture.MakeStringImgCenterAlign(strconv.Itoa(numTricks)+trickText, "", "", true, tCenter, scaler, tMax, u)
}
case 3:
diff --git a/go/src/hearts/logic/logic_test.go b/go/src/hearts/logic/logic_test.go
index 83a30f5..03d3db7 100644
--- a/go/src/hearts/logic/logic_test.go
+++ b/go/src/hearts/logic/logic_test.go
@@ -30,7 +30,7 @@
t.SetPlayedCard(card.NewCard(card.Seven, card.Heart), 2)
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 3)
t.SetPlayedCard(card.NewCard(card.Four, card.Diamond), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.EndRound()
score := players[0].GetScore()
if score != otherExpect {
@@ -63,13 +63,13 @@
t.SetPlayedCard(card.NewCard(card.Seven, card.Heart), 2)
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 3)
t.SetPlayedCard(card.NewCard(card.Four, card.Diamond), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetFirstPlayer(2)
t.SetPlayedCard(card.NewCard(card.Five, card.Diamond), 2)
t.SetPlayedCard(card.NewCard(card.Two, card.Heart), 3)
t.SetPlayedCard(card.NewCard(card.King, card.Diamond), 0)
t.SetPlayedCard(card.NewCard(card.Ace, card.Spade), 1)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.EndRound()
score := players[0].GetScore()
if score != p0Expect {
@@ -102,26 +102,26 @@
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 2)
t.SetPlayedCard(card.NewCard(card.King, card.Spade), 3)
t.SetPlayedCard(card.NewCard(card.Eight, card.Club), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetFirstPlayer(2)
t.SetPlayedCard(card.NewCard(card.Five, card.Club), 2)
t.SetPlayedCard(card.NewCard(card.Two, card.Club), 3)
t.SetPlayedCard(card.NewCard(card.King, card.Heart), 0)
t.SetPlayedCard(card.NewCard(card.Jack, card.Spade), 1)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.EndRound()
t.SetFirstPlayer(3)
t.SetPlayedCard(card.NewCard(card.Five, card.Spade), 3)
t.SetPlayedCard(card.NewCard(card.Six, card.Spade), 0)
t.SetPlayedCard(card.NewCard(card.Seven, card.Spade), 1)
t.SetPlayedCard(card.NewCard(card.Ten, card.Heart), 2)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetFirstPlayer(1)
t.SetPlayedCard(card.NewCard(card.Six, card.Diamond), 1)
t.SetPlayedCard(card.NewCard(card.Two, card.Club), 2)
t.SetPlayedCard(card.NewCard(card.King, card.Heart), 3)
t.SetPlayedCard(card.NewCard(card.Jack, card.Heart), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.EndRound()
score := players[0].GetScore()
if score != otherExpect {
@@ -186,7 +186,7 @@
// Testing playing a card-- HasSuit()
func TestSix(test *testing.T) {
- p := player.NewPlayer(0, "John", subtex)
+ p := player.NewPlayer(0)
p.AddToHand(card.NewCard(card.Six, card.Diamond))
p.AddToHand(card.NewCard(card.Four, card.Spade))
if !p.HasSuit(card.Diamond) || !p.HasSuit(card.Spade) {
@@ -199,8 +199,8 @@
// Testing playing a card-- HasAllPoints()
func TestSeven(test *testing.T) {
- p1 := player.NewPlayer(0, "John", subtex)
- p2 := player.NewPlayer(1, "Jane", subtex)
+ p1 := player.NewPlayer(0)
+ p2 := player.NewPlayer(1)
p1.AddToHand(card.NewCard(card.Six, card.Heart))
p1.AddToHand(card.NewCard(card.Queen, card.Spade))
p2.AddToHand(card.NewCard(card.Two, card.Diamond))
@@ -218,9 +218,9 @@
numPlayers := 1
t := table.InitializeGame(numPlayers, texs)
t.SetFirstPlayer(0)
- if t.ValidPlayLogic(card.NewCard(card.Eight, card.Club), 0) {
+ if t.ValidPlayLogic(card.NewCard(card.Eight, card.Club), 0) == "" {
test.Errorf("Expected invalid play for starting round with card other than 2 of Clubs")
- } else if !t.ValidPlayLogic(card.NewCard(card.Two, card.Club), 0) {
+ } else if t.ValidPlayLogic(card.NewCard(card.Two, card.Club), 0) != "" {
test.Errorf("Expected valid play for starting round with 2 of Clubs")
}
}
@@ -234,7 +234,7 @@
players[1].AddToHand(card.NewCard(card.Three, card.Diamond))
t.SetFirstPlayer(0)
t.SetPlayedCard(card.NewCard(card.Two, card.Club), 0)
- if t.ValidPlayLogic(card.NewCard(card.Queen, card.Spade), 1) {
+ if t.ValidPlayLogic(card.NewCard(card.Queen, card.Spade), 1) == "" {
test.Errorf("Expected invalid play for points on the first round")
}
}
@@ -250,21 +250,21 @@
t.SetFirstPlayer(0)
t.SetPlayedCard(card.NewCard(card.Two, card.Club), 0)
t.SetPlayedCard(card.NewCard(card.Three, card.Club), 1)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetFirstPlayer(0)
- if !t.ValidPlayLogic(card.NewCard(card.Five, card.Heart), 0) {
+ if t.ValidPlayLogic(card.NewCard(card.Five, card.Heart), 0) != "" {
test.Errorf("Expected valid play for opener rightfully breaking Hearts")
}
t.SetFirstPlayer(1)
- if t.ValidPlayLogic(card.NewCard(card.Two, card.Heart), 1) {
+ if t.ValidPlayLogic(card.NewCard(card.Two, card.Heart), 1) == "" {
test.Errorf("Expected invalid play for opener wrongfully breaking Hearts")
}
t.SetPlayedCard(card.NewCard(card.Three, card.Diamond), 1)
- if !t.ValidPlayLogic(card.NewCard(card.Five, card.Heart), 0) {
+ if t.ValidPlayLogic(card.NewCard(card.Five, card.Heart), 0) != "" {
test.Errorf("Expected valid play for follower rightfully breaking Hearts")
}
players[0].AddToHand(card.NewCard(card.Seven, card.Diamond))
- if t.ValidPlayLogic(card.NewCard(card.Five, card.Heart), 0) {
+ if t.ValidPlayLogic(card.NewCard(card.Five, card.Heart), 0) == "" {
test.Errorf("Expected invalid play for follower wrongfully breaking Hearts")
}
}
@@ -278,14 +278,14 @@
players[1].AddToHand(card.NewCard(card.Three, card.Diamond))
t.SetFirstPlayer(0)
t.SetPlayedCard(card.NewCard(card.Two, card.Club), 0)
- if !t.ValidPlayLogic(card.NewCard(card.Three, card.Diamond), 1) {
+ if t.ValidPlayLogic(card.NewCard(card.Three, card.Diamond), 1) != "" {
test.Errorf("Expected valid play for not following suit when player doesn't have suit")
}
players[1].AddToHand(card.NewCard(card.Five, card.Club))
- if !t.ValidPlayLogic(card.NewCard(card.Five, card.Club), 1) {
+ if t.ValidPlayLogic(card.NewCard(card.Five, card.Club), 1) != "" {
test.Errorf("Expected valid play for following suit")
}
- if t.ValidPlayLogic(card.NewCard(card.Three, card.Diamond), 1) {
+ if t.ValidPlayLogic(card.NewCard(card.Three, card.Diamond), 1) == "" {
test.Errorf("Expected invalid play for not following suit when player has suit")
}
}
@@ -296,33 +296,34 @@
t := table.InitializeGame(numPlayers, texs)
t.SetFirstPlayer(0)
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
- winner := t.EndRound()
+ t.SendTrick(t.GetTrickRecipient())
+ _, winners := t.EndRound()
expect := 0
- if len(winner) != expect {
- test.Errorf("Expected %d, got %d", expect, winner)
+ if len(winners) != expect {
+ test.Errorf("Expected %d, got %d", expect, winners[0])
}
t.NewRound()
+ t.SetFirstPlayer(0)
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
+ t.SendTrick(t.GetTrickRecipient())
t.SetPlayedCard(card.NewCard(card.Queen, card.Spade), 0)
- t.SendTrick()
- winner = t.EndRound()
+ t.SendTrick(t.GetTrickRecipient())
+ _, winners = t.EndRound()
expect = 0
- if winner[0] != expect {
- test.Errorf("Expected %d, got %d", expect, winner)
+ if winners[0] != expect {
+ test.Errorf("Expected %d, got %d", expect, winners[0])
}
}
diff --git a/go/src/hearts/logic/table/table.go b/go/src/hearts/logic/table/table.go
index 7b156a1..383de1b 100644
--- a/go/src/hearts/logic/table/table.go
+++ b/go/src/hearts/logic/table/table.go
@@ -223,6 +223,16 @@
return true
}
+// Returns true if all players have played a card in the current trick
+func (t *Table) TrickOver() bool {
+ for _, c := range t.trick {
+ if c == nil {
+ return false
+ }
+ }
+ return true
+}
+
// Returns true if all players are out of cards, indicating the end of a round
func (t *Table) RoundOver() bool {
for _, p := range t.players {
@@ -233,8 +243,8 @@
return true
}
-// Calculates who should take the cards in the current trick and sends them. Sets next first player accordingly. Returns true if the round is over
-func (t *Table) SendTrick() (bool, int) {
+// Calculates who should take the cards in the current trick
+func (t *Table) GetTrickRecipient() int {
trickSuit := t.trick[t.firstPlayer].GetSuit()
highestCardFace := card.Two
highestIndex := -1
@@ -245,22 +255,27 @@
highestIndex = i
}
}
+ return highestIndex
+}
+
+// Sends cards to recipient. Sets next first player accordingly. Returns true if the round is over
+func (t *Table) SendTrick(recipient int) bool {
// resets all players' donePlaying bools
for _, p := range t.players {
p.SetDonePlaying(false)
}
// clear trick
- t.players[highestIndex].TakeTrick(t.trick)
+ t.players[recipient].TakeTrick(t.trick)
t.trick = make([]*card.Card, len(t.players))
if t.firstTrick {
t.firstTrick = false
}
if t.RoundOver() {
- return true, highestIndex
+ return true
}
// set first player for next trick to whoever received the current trick
- t.SetFirstPlayer(highestIndex)
- return false, highestIndex
+ t.SetFirstPlayer(recipient)
+ return false
}
// Returns the score of the current round
diff --git a/go/src/hearts/main.go b/go/src/hearts/main.go
index de2ab74..38eb093 100644
--- a/go/src/hearts/main.go
+++ b/go/src/hearts/main.go
@@ -100,9 +100,7 @@
namespace.SetPermissions(u.Ctx, sync.MountPoint+"/croupier", permissions, "")
u.Service.SetPermissions(u.Ctx, permissions, "")
u.Images = glutil.NewImages(glctx)
- if u.Debug {
- fps = debug.NewFPS(u.Images)
- }
+ fps = debug.NewFPS(u.Images)
u.Eng = glsprite.Engine(u.Images)
u.Texs = texture.LoadTextures(u.Eng)
u.CurTable = table.InitializeGame(u.NumPlayers, u.Texs)
@@ -113,9 +111,7 @@
func onStop(u *uistate.UIState) {
u.Eng.Release()
- if u.Debug {
- fps.Release()
- }
+ fps.Release()
u.Images.Release()
u.Done = true
u.Shutdown()
diff --git a/go/src/hearts/sync/logWriter.go b/go/src/hearts/sync/logWriter.go
index 3e575e8..110d0dd 100644
--- a/go/src/hearts/sync/logWriter.go
+++ b/go/src/hearts/sync/logWriter.go
@@ -24,16 +24,17 @@
)
const (
- Deal string = "Deal"
- Pass string = "Pass"
- Take string = "Take"
- Play string = "Play"
- Ready string = "Ready"
- Bar string = "|"
- Space string = " "
- Colon string = ":"
- Dash string = "-"
- End string = "END"
+ Deal string = "Deal"
+ Pass string = "Pass"
+ Take string = "Take"
+ Play string = "Play"
+ Ready string = "Ready"
+ TakeTrick string = "TakeTrick"
+ Bar string = "|"
+ Space string = " "
+ Colon string = ":"
+ Dash string = "-"
+ End string = "END"
)
// Formats deal command and sends to Syncbase
@@ -87,6 +88,12 @@
return logKeyValue(u.Service, u.Ctx, key, value)
}
+func LogTakeTrick(u *uistate.UIState) bool {
+ key := getKey(u.CurPlayerIndex, u)
+ value := TakeTrick + Bar + End
+ return logKeyValue(u.Service, u.Ctx, key, value)
+}
+
func LogPlayerNum(u *uistate.UIState) bool {
key := fmt.Sprintf("%d/players/%d/player_number", u.GameID, UserID)
value := strconv.Itoa(u.CurPlayerIndex)
diff --git a/go/src/hearts/sync/util.go b/go/src/hearts/sync/util.go
index b1da39f..7ee4d6d 100644
--- a/go/src/hearts/sync/util.go
+++ b/go/src/hearts/sync/util.go
@@ -8,13 +8,13 @@
const (
// switch back to my mountpoint with the following code:
- //MountPoint = "users/emshack@google.com"
- MountPoint = "/192.168.86.254:8101"
- UserID = 1111
+ MountPoint = "users/emshack@google.com"
+ //MountPoint = "/192.168.86.254:8101"
+ UserID = 2222
UserColor = 16777215
- UserAvatar = "player0.jpeg"
- UserName = "Alice"
- SBName = "syncbase"
+ UserAvatar = "player1.jpeg"
+ UserName = "Bob"
+ SBName = "syncbase1"
AppName = "app"
DbName = "db"
LogName = "games"
diff --git a/go/src/hearts/sync/watch.go b/go/src/hearts/sync/watch.go
index e458cf4..4057809 100644
--- a/go/src/hearts/sync/watch.go
+++ b/go/src/hearts/sync/watch.go
@@ -12,6 +12,7 @@
import (
"encoding/json"
"fmt"
+ "golang.org/x/mobile/exp/sprite"
"hearts/img/direction"
"hearts/img/reposition"
"hearts/img/uistate"
@@ -20,7 +21,6 @@
"sort"
"strconv"
"strings"
- "time"
"v.io/v23/syncbase/nosql"
)
@@ -134,6 +134,8 @@
onTake(valueStr, u)
case Play:
onPlay(valueStr, u)
+ case TakeTrick:
+ onTakeTrick(valueStr, u)
case Ready:
onReady(valueStr, u)
}
@@ -156,11 +158,21 @@
userID, _ := strconv.Atoi(strings.Split(key, "/")[2])
playerNum, _ := strconv.Atoi(value)
u.PlayerData[playerNum] = userID
+ u.CurTable.GetPlayers()[playerNum].SetDoneScoring(true)
if playerNum == u.CurPlayerIndex && userID != UserID {
u.CurPlayerIndex = -1
}
if u.CurView == uistate.Arrange {
view.LoadArrangeView(u)
+ if u.CurTable.AllReadyForNewRound() && u.IsOwner {
+ b := u.Buttons["start"]
+ u.Eng.SetSubTex(b.GetNode(), b.GetImage())
+ b.SetDisplayingImage(true)
+ if u.SGChan != nil {
+ u.SGChan <- true
+ u.SGChan = nil
+ }
+ }
}
}
@@ -262,22 +274,10 @@
u.CurTable.GetPlayers()[playerInt].RemoveFromHand(playedCard)
u.CurTable.SetPlayedCard(playedCard, playerInt)
u.CurTable.GetPlayers()[playerInt].SetDonePlaying(true)
- trickOver := true
- trickCards := u.CurTable.GetTrick()
- for _, c := range trickCards {
- if c == nil {
- trickOver = false
- }
- }
- roundOver := false
+ trickOver := u.CurTable.TrickOver()
var recipient int
if trickOver {
- roundOver, recipient = u.CurTable.SendTrick()
- }
- var roundScores []int
- var winners []int
- if roundOver {
- roundScores, winners = u.CurTable.EndRound()
+ recipient = u.CurTable.GetTrickRecipient()
}
// UI
if u.CurView == uistate.Table {
@@ -286,65 +286,85 @@
reposition.AnimateTableCardPlay(playedCard, playerInt, quit, u)
reposition.SetTableDropColors(u)
if trickOver {
+ // display take trick button
+ b := u.Buttons["takeTrick"]
+ u.Eng.SetSubTex(b.GetNode(), b.GetImage())
+ }
+ } else if u.CurView == uistate.Split {
+ if playerInt != u.CurPlayerIndex {
+ quit := make(chan bool)
+ u.AnimChans = append(u.AnimChans, quit)
+ reposition.AnimateSplitCardPlay(playedCard, playerInt, quit, u)
+ }
+ reposition.SetSplitDropColors(u)
+ view.LoadSplitView(true, u)
+ if trickOver {
+ if recipient == u.CurPlayerIndex {
+ // display take trick button
+ b := u.Buttons["takeTrick"]
+ u.Eng.SetSubTex(b.GetNode(), b.GetImage())
+ }
+ }
+ } else if u.CurView == uistate.Play && u.CurPlayerIndex != playerInt {
+ view.LoadPlayView(u)
+ }
+}
+
+func onTakeTrick(value string, u *uistate.UIState) {
+ trickCards := u.CurTable.GetTrick()
+ recipient := u.CurTable.GetTrickRecipient()
+ roundOver := u.CurTable.SendTrick(recipient)
+ var roundScores []int
+ var winners []int
+ if roundOver {
+ roundScores, winners = u.CurTable.EndRound()
+ }
+ // UI
+ if u.CurView == uistate.Table {
+ var emptyTex sprite.SubTex
+ u.Eng.SetSubTex(u.Buttons["takeTrick"].GetNode(), emptyTex)
+ var trickDir direction.Direction
+ switch recipient {
+ case 0:
+ trickDir = direction.Down
+ case 1:
+ trickDir = direction.Left
+ case 2:
+ trickDir = direction.Across
+ case 3:
+ trickDir = direction.Right
+ }
+ quit := make(chan bool)
+ u.AnimChans = append(u.AnimChans, quit)
+ reposition.AnimateTableCardTakeTrick(trickCards, trickDir, quit, u)
+ reposition.SetTableDropColors(u)
+ view.SetNumTricksTable(u)
+ } else if u.CurView == uistate.Split {
+ var emptyTex sprite.SubTex
+ u.Eng.SetSubTex(u.Buttons["takeTrick"].GetNode(), emptyTex)
+ if roundOver {
+ view.LoadScoreView(roundScores, winners, u)
+ } else {
var trickDir direction.Direction
switch recipient {
- case 0:
+ case u.CurPlayerIndex:
trickDir = direction.Down
- case 1:
+ case (u.CurPlayerIndex + 1) % u.NumPlayers:
trickDir = direction.Left
- case 2:
+ case (u.CurPlayerIndex + 2) % u.NumPlayers:
trickDir = direction.Across
- case 3:
+ case (u.CurPlayerIndex + 3) % u.NumPlayers:
trickDir = direction.Right
}
quit := make(chan bool)
u.AnimChans = append(u.AnimChans, quit)
reposition.AnimateTableCardTakeTrick(trickCards, trickDir, quit, u)
- view.SetNumTricksTable(u)
- }
- } else if u.CurView == uistate.Split {
- if roundOver {
- view.LoadScoreView(roundScores, winners, u)
- } else {
- if playerInt != u.CurPlayerIndex {
- quit := make(chan bool)
- u.AnimChans = append(u.AnimChans, quit)
- reposition.AnimateSplitCardPlay(playedCard, playerInt, quit, u)
- }
- reposition.SetSplitDropColors(u)
- if trickOver {
- var trickDir direction.Direction
- switch recipient {
- case u.CurPlayerIndex:
- trickDir = direction.Down
- case (u.CurPlayerIndex + 1) % u.NumPlayers:
- trickDir = direction.Left
- case (u.CurPlayerIndex + 2) % u.NumPlayers:
- trickDir = direction.Across
- case (u.CurPlayerIndex + 3) % u.NumPlayers:
- trickDir = direction.Right
- }
- quit := make(chan bool)
- u.AnimChans = append(u.AnimChans, quit)
- reposition.AnimateTableCardTakeTrick(trickCards, trickDir, quit, u)
- }
view.LoadSplitView(true, u)
}
} else if u.CurView == uistate.Play {
if roundOver {
view.LoadScoreView(roundScores, winners, u)
- } else if trickOver {
- if u.CurPlayerIndex != recipient {
- message := uistate.GetName(recipient, u) + "'s trick"
- view.ChangePlayMessage(message, u)
- <-time.After(2 * time.Second)
- view.LoadPlayView(u)
- } else {
- view.ChangePlayMessage("Your trick", u)
- <-time.After(2 * time.Second)
- view.LoadPlayView(u)
- }
- } else if u.CurPlayerIndex != playerInt {
+ } else {
view.LoadPlayView(u)
}
}
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index f66ae14..f69a541 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -10,6 +10,7 @@
"fmt"
"strconv"
"strings"
+ "time"
"golang.org/x/mobile/event/touch"
"golang.org/x/mobile/exp/sprite"
@@ -22,12 +23,35 @@
"hearts/sync"
)
+var (
+ numTaps int
+ beganTouchX float32
+ beganTouchY float32
+ timeStartedTapping = time.Now()
+)
+
func OnTouch(t touch.Event, u *uistate.UIState) {
if t.Type == touch.TypeBegin {
u.ViewOnTouch = u.CurView
+ beganTouchX = t.X
+ beganTouchY = t.Y
} else if u.CurView != u.ViewOnTouch {
return
}
+ // tap 5 times to trigger debug mode
+ if t.Type == touch.TypeEnd {
+ if t.X == beganTouchX && t.Y == beganTouchY && time.Since(timeStartedTapping).Seconds() <= 5.0 {
+ numTaps++
+ if numTaps == 5 {
+ fmt.Println("TOGGLING DEBUG")
+ u.Debug = !u.Debug
+ numTaps = 0
+ }
+ } else {
+ numTaps = 0
+ timeStartedTapping = time.Now()
+ }
+ }
switch u.CurView {
case uistate.Discovery:
switch t.Type {
@@ -51,6 +75,10 @@
switch t.Type {
case touch.TypeBegin:
beginClickTable(t, u)
+ case touch.TypeMove:
+ moveClickTable(t, u)
+ case touch.TypeEnd:
+ endClickTable(t, u)
}
case uistate.Pass:
switch t.Type {
@@ -93,14 +121,9 @@
case touch.TypeBegin:
beginClickSplit(t, u)
case touch.TypeMove:
- if u.CurCard != nil {
- moveClickSplit(t, u)
- }
+ moveClickSplit(t, u)
case touch.TypeEnd:
- if u.CurCard != nil {
- endClickSplit(t, u.CurCard, u)
- u.CurCard = nil
- }
+ endClickSplit(t, u)
}
case uistate.Score:
switch t.Type {
@@ -228,7 +251,6 @@
} else {
playerNum := strings.Split(key, "-")[1]
u.CurPlayerIndex, _ = strconv.Atoi(playerNum)
- sync.LogReady(u)
sync.LogPlayerNum(u)
}
}
@@ -240,7 +262,28 @@
func beginClickTable(t touch.Event, u *uistate.UIState) {
buttonList := findClickedButton(t, u)
if len(buttonList) > 0 {
- updateViewFromTable(buttonList[0], u)
+ if buttonList[0] == u.Buttons["takeTrick"] {
+ pressButton(buttonList[0], u)
+ } else {
+ updateViewFromTable(buttonList[0], u)
+ }
+ }
+}
+
+func moveClickTable(t touch.Event, u *uistate.UIState) {
+ curPressed := findClickedButton(t, u)
+ alreadyPressed := getPressed(u)
+ if len(alreadyPressed) > 0 && len(curPressed) == 0 {
+ unpressButtons(u)
+ }
+}
+
+func endClickTable(t touch.Event, u *uistate.UIState) {
+ pressed := unpressButtons(u)
+ for _, b := range pressed {
+ if b == u.Buttons["takeTrick"] {
+ sync.LogTakeTrick(u)
+ }
}
}
@@ -360,7 +403,7 @@
// add card back to hand
reposition.ResetCardPosition(c, u.Eng)
reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
- doneTaking := true
+ doneTaking := len(u.DropTargets) == 3
for _, d := range u.DropTargets {
if d.GetCardHere() != nil {
doneTaking = false
@@ -450,6 +493,8 @@
}
reposition.SwitchOnChan(ch, quit, onDone, u)
}()
+ } else if b == u.Buttons["takeTrick"] {
+ pressButton(b, u)
} else if b == u.Buttons["table"] {
view.LoadTableView(u)
} else if b == u.Buttons["hand"] {
@@ -459,21 +504,36 @@
}
func moveClickSplit(t touch.Event, u *uistate.UIState) {
- reposition.DragCard(t, u)
+ if u.CurCard != nil {
+ reposition.DragCard(t, u)
+ }
+ curPressed := findClickedButton(t, u)
+ alreadyPressed := getPressed(u)
+ if len(alreadyPressed) > 0 && len(curPressed) == 0 {
+ unpressButtons(u)
+ }
}
-func endClickSplit(t touch.Event, c *card.Card, u *uistate.UIState) {
- if dropCardHere(c, u.DropTargets[0], t, u) {
- ch := make(chan bool)
- if err := playCard(ch, u.CurPlayerIndex, u); err != "" {
- view.ChangePlayMessage(err, u)
- removeCardFromTarget(c, u)
+func endClickSplit(t touch.Event, u *uistate.UIState) {
+ if u.CurCard != nil {
+ if dropCardHere(u.CurCard, u.DropTargets[0], t, u) {
+ ch := make(chan bool)
+ if err := playCard(ch, u.CurPlayerIndex, u); err != "" {
+ view.ChangePlayMessage(err, u)
+ removeCardFromTarget(u.CurCard, u)
+ // add card back to hand
+ reposition.ResetCardPosition(u.CurCard, u.Eng)
+ }
+ } else {
// add card back to hand
- reposition.ResetCardPosition(c, u.Eng)
+ reposition.ResetCardPosition(u.CurCard, u.Eng)
}
- } else {
- // add card back to hand
- reposition.ResetCardPosition(c, u.Eng)
+ }
+ pressed := unpressButtons(u)
+ for _, b := range pressed {
+ if b == u.Buttons["takeTrick"] {
+ sync.LogTakeTrick(u)
+ }
}
}