Fixed animation issue
Updates to hand views

Change-Id: I90fa669778998d343c4c3c7cc9b25fc3069e8e94
diff --git a/go/Makefile b/go/Makefile
index 9b30352..416578f 100644
--- a/go/Makefile
+++ b/go/Makefile
@@ -24,7 +24,7 @@
 
 .PHONY:
 delete:
-	rm -rf tmp/syncbase_
+	rm -rf tmp/syncbase_$(id)
 
 # Naming collisions for different instances of syncbase for the same user?
 # Easy way to make --v23.permissions.literal?
diff --git a/go/src/hearts/Makefile b/go/src/hearts/Makefile
index a273486..9b44e5c 100644
--- a/go/src/hearts/Makefile
+++ b/go/src/hearts/Makefile
@@ -15,7 +15,7 @@
 	./hearts \
     --v23.proxy=proxy \
     --v23.tcp.address=:$(syncbase_port) \
-	--v23.credentials=../../credentials
+	--v23.credentials=credentials
 
 test:
 	jiri go test hearts/...
diff --git a/go/src/hearts/assets/Apostrophe-DBlue.png b/go/src/hearts/assets/Apostrophe-DBlue.png
new file mode 100644
index 0000000..3db2a82
--- /dev/null
+++ b/go/src/hearts/assets/Apostrophe-DBlue.png
Binary files differ
diff --git a/go/src/hearts/assets/Rectangle-DBlue.png b/go/src/hearts/assets/Rectangle-DBlue.png
new file mode 100644
index 0000000..11a72b9
--- /dev/null
+++ b/go/src/hearts/assets/Rectangle-DBlue.png
Binary files differ
diff --git a/go/src/hearts/assets/Space-DBlue.png b/go/src/hearts/assets/Space-DBlue.png
new file mode 100644
index 0000000..8b17e87
--- /dev/null
+++ b/go/src/hearts/assets/Space-DBlue.png
Binary files differ
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index 8b8b26d..7feaee2 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -7,9 +7,6 @@
 package reposition
 
 import (
-	"math"
-	"time"
-
 	"hearts/img/coords"
 	"hearts/img/direction"
 	"hearts/img/staticimg"
@@ -24,8 +21,7 @@
 
 const (
 	// animationFrameCounter is the number of frames it will take to complete any animation
-	// This is a float because it allows for future float operations without requiring conversion each time
-	animationFrameCounter = float32(100)
+	animationFrameCounter = 100
 	// animRotationScaler is the speed at which an image rotates, if rotation is involved in an animation
 	animRotationScaler = .15
 )
@@ -82,14 +78,6 @@
 	}
 }
 
-// Animation for the 'take' action, when app is in the table view
-func AnimateTableCardTake(animCard *card.Card, cardNum int, p *player.Player) {
-	destinationPos := p.GetPassedFrom()[cardNum].GetInitial()
-	c := make(chan bool)
-	animateCardMovement(c, animCard, destinationPos, animCard.GetDimensions())
-	<-c
-}
-
 // Animation for the 'pass' action, when app is in the table view
 func AnimateTableCardPass(animCard *card.Card, toPlayer, cardNum int, u *uistate.UIState) {
 	cardDim := animCard.GetDimensions()
@@ -123,52 +111,16 @@
 	<-c
 }
 
-// Animation for the 'pass' action, when app is in the hand view
-func AnimateHandCardPass(ch chan bool, animImages []*staticimg.StaticImg, animCards []*card.Card, u *uistate.UIState) {
-	ch2 := make(chan bool)
-	for _, i := range animImages {
-		dims := i.GetDimensions()
-		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y-u.WindowSize.Y)
-		AnimateImageMovement(i, to, dims)
-	}
-	for _, c := range animCards {
-		dims := c.GetDimensions()
-		to := coords.MakeVec(c.GetCurrent().X, c.GetCurrent().Y-u.WindowSize.Y)
-		animateCardMovement(ch2, c, to, dims)
-	}
-	select {
-	case <-ch2:
-		ch <- true
-	case <-time.After(1 * time.Second):
-		ch <- false
-	}
-}
-
-// Animation for the 'take' action, when app is in the hand view
-func AnimateHandCardTake(ch chan bool, animImages []*staticimg.StaticImg, u *uistate.UIState) {
-	ch2 := make(chan bool)
-	for _, i := range animImages {
-		destination := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y-u.WindowSize.Y)
-		AnimateImageMovement(i, destination, i.GetDimensions())
-	}
-	select {
-	case <-ch2:
-		ch <- true
-	case <-time.After(1 * time.Second):
-		ch <- false
-	}
-}
-
-// Animation for the 'play' action, when app is in the hand view
-func AnimateHandCardPlay(c chan bool, animCard *card.Card, u *uistate.UIState) {
-	destination := determineDestination(animCard, direction.Across, u.WindowSize)
-	animateCardMovement(c, animCard, destination, animCard.GetDimensions())
+// Animation for the 'take' action, when app is in the table view
+func AnimateTableCardTake(animCard *card.Card, cardNum int, p *player.Player) {
+	destinationPos := p.GetPassedFrom()[cardNum].GetInitial()
+	c := make(chan bool)
+	animateCardMovement(c, animCard, destinationPos, animCard.GetDimensions())
 	<-c
-	c <- true
 }
 
 // Animation for the 'play' action, when app is in the table view
-func AnimateTableCardPlay(c chan bool, animCard *card.Card, playerInt int, u *uistate.UIState) {
+func AnimateTableCardPlay(animCard *card.Card, playerInt int, u *uistate.UIState) {
 	destination := u.DropTargets[playerInt]
 	destinationPos := destination.GetCurrent()
 	destinationDim := destination.GetDimensions()
@@ -176,7 +128,79 @@
 	animateCardMovement(ch, animCard, destinationPos, destinationDim)
 	<-ch
 	animCard.SetFrontDisplay(u.Eng)
-	c <- true
+}
+
+// Animation for the 'pass' action, when app is in the hand view
+func AnimateHandCardPass(ch chan bool, animImages []*staticimg.StaticImg, animCards []*card.Card, u *uistate.UIState) {
+	for _, i := range animImages {
+		dims := i.GetDimensions()
+		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y-u.WindowSize.Y)
+		AnimateImageNoChannel(i, to, dims)
+	}
+	for i, c := range animCards {
+		dims := c.GetDimensions()
+		to := coords.MakeVec(c.GetCurrent().X, c.GetCurrent().Y-u.WindowSize.Y)
+		if i < len(animCards)-1 {
+			animateCardNoChannel(c, to, dims)
+		} else {
+			animateCardMovement(ch, c, to, dims)
+		}
+	}
+}
+
+// Animation for the 'take' action, when app is in the hand view
+func AnimateHandCardTake(ch chan bool, animImages []*staticimg.StaticImg, u *uistate.UIState) {
+	for i, image := range animImages {
+		destination := coords.MakeVec(image.GetCurrent().X, image.GetCurrent().Y-u.WindowSize.Y)
+		if i < len(animImages)-1 {
+			AnimateImageNoChannel(image, destination, image.GetDimensions())
+		} else {
+			animateImageMovement(ch, image, destination, image.GetDimensions())
+		}
+	}
+}
+
+// Animation to bring in the take slot
+func AnimateInTake(u *uistate.UIState) {
+	imgs := append(u.Other, u.DropTargets...)
+	passedCards := u.CurTable.GetPlayers()[u.CurPlayerIndex].GetPassedTo()
+	for _, i := range imgs {
+		dims := i.GetDimensions()
+		var to *coords.Vec
+		if passedCards == nil {
+			to = coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y/5)
+		} else {
+			to = coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y/2)
+		}
+		AnimateImageNoChannel(i, to, dims)
+	}
+	for _, c := range passedCards {
+		dims := c.GetDimensions()
+		to := coords.MakeVec(c.GetCurrent().X, c.GetCurrent().Y+u.WindowSize.Y/2)
+		animateCardNoChannel(c, to, dims)
+	}
+}
+
+// Animation for the 'play' action, when app is in the hand view
+func AnimateHandCardPlay(ch chan bool, animCard *card.Card, u *uistate.UIState) {
+	imgs := []*staticimg.StaticImg{u.Other[0], u.DropTargets[0]}
+	for _, i := range imgs {
+		dims := i.GetDimensions()
+		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y-u.WindowSize.Y)
+		AnimateImageNoChannel(i, to, dims)
+	}
+	to := coords.MakeVec(animCard.GetCurrent().X, animCard.GetCurrent().Y-u.WindowSize.Y)
+	animateCardMovement(ch, animCard, to, animCard.GetDimensions())
+}
+
+// Animation to bring in the play slot when app is in the hand view and it is the player's turn
+func AnimateInPlay(u *uistate.UIState) {
+	imgs := []*staticimg.StaticImg{u.Other[0], u.DropTargets[0]}
+	for _, i := range imgs {
+		dims := i.GetDimensions()
+		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y/3)
+		AnimateImageNoChannel(i, to, dims)
+	}
 }
 
 func determineDestination(animCard *card.Card, dir direction.Direction, windowSize *coords.Vec) *coords.Vec {
@@ -196,21 +220,21 @@
 }
 
 // Animation for when a trick is taken, when app is in the table view
-func AnimateTableCardTakeTrick(c chan bool, animCard *card.Card, dir direction.Direction, u *uistate.UIState) {
+func AnimateTableCardTakeTrick(animCard *card.Card, dir direction.Direction, u *uistate.UIState) {
 	destination := determineDestination(animCard, dir, u.WindowSize)
+	c := make(chan bool)
 	animateCardMovement(c, animCard, destination, animCard.GetDimensions())
 	<-c
-	c <- true
 }
 
-func AnimateImageMovement(animImage *staticimg.StaticImg, endPos, endDim *coords.Vec) {
+func animateImageMovement(c chan bool, animImage *staticimg.StaticImg, endPos, endDim *coords.Vec) {
 	node := animImage.GetNode()
 	startPos := animImage.GetCurrent()
 	startDim := animImage.GetDimensions()
 	iteration := 0
 	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
 		iteration++
-		if float32(iteration) < animationFrameCounter {
+		if iteration < animationFrameCounter {
 			curXY := animImage.GetCurrent()
 			curDim := animImage.GetDimensions()
 			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCounter)
@@ -218,7 +242,29 @@
 			newVec := curXY.PlusVec(XYStep)
 			dimVec := curDim.PlusVec(dimStep)
 			animImage.Move(newVec, dimVec, eng)
-		} else if math.Abs(float64(animationFrameCounter)-float64(iteration)) < 0.0001 {
+		} else if iteration == animationFrameCounter {
+			animImage.Move(endPos, endDim, eng)
+			c <- true
+		}
+	})
+}
+
+func AnimateImageNoChannel(animImage *staticimg.StaticImg, endPos, endDim *coords.Vec) {
+	node := animImage.GetNode()
+	startPos := animImage.GetCurrent()
+	startDim := animImage.GetDimensions()
+	iteration := 0
+	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
+		iteration++
+		if iteration < animationFrameCounter {
+			curXY := animImage.GetCurrent()
+			curDim := animImage.GetDimensions()
+			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCounter)
+			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCounter)
+			newVec := curXY.PlusVec(XYStep)
+			dimVec := curDim.PlusVec(dimStep)
+			animImage.Move(newVec, dimVec, eng)
+		} else if iteration == animationFrameCounter {
 			animImage.Move(endPos, endDim, eng)
 		}
 	})
@@ -231,7 +277,7 @@
 	iteration := 0
 	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
 		iteration++
-		if float32(iteration) < animationFrameCounter {
+		if iteration < animationFrameCounter {
 			curXY := animCard.GetCurrent()
 			curDim := animCard.GetDimensions()
 			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCounter)
@@ -239,13 +285,34 @@
 			newVec := curXY.PlusVec(XYStep)
 			dimVec := curDim.PlusVec(dimStep)
 			animCard.Move(newVec, dimVec, eng)
-		} else if math.Abs(float64(animationFrameCounter)-float64(iteration)) < 0.0001 {
+		} else if iteration == animationFrameCounter {
 			animCard.Move(endPos, endDim, eng)
 			c <- true
 		}
 	})
 }
 
+func animateCardNoChannel(animCard *card.Card, endPos, endDim *coords.Vec) {
+	node := animCard.GetNode()
+	startPos := animCard.GetCurrent()
+	startDim := animCard.GetDimensions()
+	iteration := 0
+	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
+		iteration++
+		if iteration < animationFrameCounter {
+			curXY := animCard.GetCurrent()
+			curDim := animCard.GetDimensions()
+			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCounter)
+			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCounter)
+			newVec := curXY.PlusVec(XYStep)
+			dimVec := curDim.PlusVec(dimStep)
+			animCard.Move(newVec, dimVec, eng)
+		} else if iteration == animationFrameCounter {
+			animCard.Move(endPos, endDim, eng)
+		}
+	})
+}
+
 type arrangerFunc func(e sprite.Engine, n *sprite.Node, t clock.Time)
 
 // Used for node.Arranger
diff --git a/go/src/hearts/img/resize/resize.go b/go/src/hearts/img/resize/resize.go
index d9e1272..8fdbd28 100644
--- a/go/src/hearts/img/resize/resize.go
+++ b/go/src/hearts/img/resize/resize.go
@@ -22,8 +22,6 @@
 	updateWindowSize(sz, u)
 	if windowExists(oldWindowSize) && windowExists(u.WindowSize) {
 		u.Padding = scaleVar(u.Padding, oldWindowSize, u.WindowSize)
-		u.CardDim = scaleVec(u.CardDim, oldWindowSize, u.WindowSize)
-		u.TableCardDim = scaleVec(u.TableCardDim, oldWindowSize, u.WindowSize)
 		AdjustImgs(oldWindowSize, u)
 	}
 }
@@ -64,7 +62,8 @@
 // Adjusts the positioning of an individual array of images
 func adjustImgArray(imgs []*staticimg.StaticImg, oldWindowSize, newWindowSize *coords.Vec, eng sprite.Engine) {
 	for _, s := range imgs {
-		newInitial, newPos, newDimensions := AdjustScaleDimensions(s.GetInitial(), s.GetCurrent(), s.GetDimensions(), oldWindowSize, newWindowSize)
+		newInitial, newPos, newDimensions := AdjustScaleDimensions(
+			s.GetInitial(), s.GetCurrent(), s.GetDimensions(), oldWindowSize, newWindowSize)
 		s.Move(newPos, newDimensions, eng)
 		s.SetInitial(newInitial)
 	}
@@ -73,7 +72,8 @@
 // Adjusts the positioning of an individual array of cards
 func adjustCardArray(cards []*card.Card, oldWindowSize, newWindowSize *coords.Vec, eng sprite.Engine) {
 	for _, c := range cards {
-		newInitial, newPos, newDimensions := AdjustScaleDimensions(c.GetInitial(), c.GetCurrent(), c.GetDimensions(), oldWindowSize, newWindowSize)
+		newInitial, newPos, newDimensions := AdjustScaleDimensions(
+			c.GetInitial(), c.GetCurrent(), c.GetDimensions(), oldWindowSize, newWindowSize)
 		c.Move(newPos, newDimensions, eng)
 		c.SetInitial(newInitial)
 	}
diff --git a/go/src/hearts/img/texture/texture.go b/go/src/hearts/img/texture/texture.go
index f661ad2..9da057d 100644
--- a/go/src/hearts/img/texture/texture.go
+++ b/go/src/hearts/img/texture/texture.go
@@ -66,6 +66,9 @@
 			key += "Space"
 		} else if char == 33 {
 			key += "Bang"
+			// if char is an apostrophe
+		} else if char == 39 {
+			key += "Apostrophe"
 			// if char is a colon
 		} else if char == 58 {
 			key += "Colon"
@@ -247,26 +250,27 @@
 		"D-Lower-DBlue.png", "E-Lower-DBlue.png", "F-Lower-DBlue.png", "G-Lower-DBlue.png", "H-Lower-DBlue.png", "I-Lower-DBlue.png",
 		"J-Lower-DBlue.png", "K-Lower-DBlue.png", "L-Lower-DBlue.png", "M-Lower-DBlue.png", "N-Lower-DBlue.png", "O-Lower-DBlue.png",
 		"P-Lower-DBlue.png", "Q-Lower-DBlue.png", "R-Lower-DBlue.png", "S-Lower-DBlue.png", "T-Lower-DBlue.png", "U-Lower-DBlue.png",
-		"V-Lower-DBlue.png", "W-Lower-DBlue.png", "X-Lower-DBlue.png", "Y-Lower-DBlue.png", "Z-Lower-DBlue.png", "A-Upper-LBlue.png",
-		"B-Upper-LBlue.png", "C-Upper-LBlue.png", "D-Upper-LBlue.png", "E-Upper-LBlue.png", "F-Upper-LBlue.png", "G-Upper-LBlue.png",
-		"H-Upper-LBlue.png", "I-Upper-LBlue.png", "J-Upper-LBlue.png", "K-Upper-LBlue.png", "L-Upper-LBlue.png", "M-Upper-LBlue.png",
-		"N-Upper-LBlue.png", "O-Upper-LBlue.png", "P-Upper-LBlue.png", "Q-Upper-LBlue.png", "R-Upper-LBlue.png", "S-Upper-LBlue.png",
-		"T-Upper-LBlue.png", "U-Upper-LBlue.png", "V-Upper-LBlue.png", "W-Upper-LBlue.png", "X-Upper-LBlue.png", "Y-Upper-LBlue.png",
-		"Z-Upper-LBlue.png", "A-Lower-LBlue.png", "B-Lower-LBlue.png", "C-Lower-LBlue.png", "D-Lower-LBlue.png", "E-Lower-LBlue.png",
-		"F-Lower-LBlue.png", "G-Lower-LBlue.png", "H-Lower-LBlue.png", "I-Lower-LBlue.png", "J-Lower-LBlue.png", "K-Lower-LBlue.png",
-		"L-Lower-LBlue.png", "M-Lower-LBlue.png", "N-Lower-LBlue.png", "O-Lower-LBlue.png", "P-Lower-LBlue.png", "Q-Lower-LBlue.png",
-		"R-Lower-LBlue.png", "S-Lower-LBlue.png", "T-Lower-LBlue.png", "U-Lower-LBlue.png", "V-Lower-LBlue.png", "W-Lower-LBlue.png",
-		"X-Lower-LBlue.png", "Y-Lower-LBlue.png", "Z-Lower-LBlue.png", "A-Upper-Gray.png", "B-Upper-Gray.png", "C-Upper-Gray.png",
-		"D-Upper-Gray.png", "E-Upper-Gray.png", "F-Upper-Gray.png", "G-Upper-Gray.png", "H-Upper-Gray.png", "I-Upper-Gray.png",
-		"J-Upper-Gray.png", "K-Upper-Gray.png", "L-Upper-Gray.png", "M-Upper-Gray.png", "N-Upper-Gray.png", "O-Upper-Gray.png",
-		"P-Upper-Gray.png", "Q-Upper-Gray.png", "R-Upper-Gray.png", "S-Upper-Gray.png", "T-Upper-Gray.png", "U-Upper-Gray.png",
-		"V-Upper-Gray.png", "W-Upper-Gray.png", "X-Upper-Gray.png", "Y-Upper-Gray.png", "Z-Upper-Gray.png", "A-Lower-Gray.png",
-		"B-Lower-Gray.png", "C-Lower-Gray.png", "D-Lower-Gray.png", "E-Lower-Gray.png", "F-Lower-Gray.png", "G-Lower-Gray.png",
-		"H-Lower-Gray.png", "I-Lower-Gray.png", "J-Lower-Gray.png", "K-Lower-Gray.png", "L-Lower-Gray.png", "M-Lower-Gray.png",
-		"N-Lower-Gray.png", "O-Lower-Gray.png", "P-Lower-Gray.png", "Q-Lower-Gray.png", "R-Lower-Gray.png", "S-Lower-Gray.png",
-		"T-Lower-Gray.png", "U-Lower-Gray.png", "V-Lower-Gray.png", "W-Lower-Gray.png", "X-Lower-Gray.png", "Y-Lower-Gray.png",
-		"Z-Lower-Gray.png", "Space-Gray.png", "RoundedRectangle-DBlue.png", "RoundedRectangle-LBlue.png", "RoundedRectangle-Gray.png",
-		"Rectangle-LBlue.png", "HorizontalPullTab.png", "VerticalPullTab.png",
+		"V-Lower-DBlue.png", "W-Lower-DBlue.png", "X-Lower-DBlue.png", "Y-Lower-DBlue.png", "Z-Lower-DBlue.png", "Apostrophe-DBlue.png",
+		"Space-DBlue.png", "A-Upper-LBlue.png", "B-Upper-LBlue.png", "C-Upper-LBlue.png", "D-Upper-LBlue.png", "E-Upper-LBlue.png",
+		"F-Upper-LBlue.png", "G-Upper-LBlue.png", "H-Upper-LBlue.png", "I-Upper-LBlue.png", "J-Upper-LBlue.png", "K-Upper-LBlue.png",
+		"L-Upper-LBlue.png", "M-Upper-LBlue.png", "N-Upper-LBlue.png", "O-Upper-LBlue.png", "P-Upper-LBlue.png", "Q-Upper-LBlue.png",
+		"R-Upper-LBlue.png", "S-Upper-LBlue.png", "T-Upper-LBlue.png", "U-Upper-LBlue.png", "V-Upper-LBlue.png", "W-Upper-LBlue.png",
+		"X-Upper-LBlue.png", "Y-Upper-LBlue.png", "Z-Upper-LBlue.png", "A-Lower-LBlue.png", "B-Lower-LBlue.png", "C-Lower-LBlue.png",
+		"D-Lower-LBlue.png", "E-Lower-LBlue.png", "F-Lower-LBlue.png", "G-Lower-LBlue.png", "H-Lower-LBlue.png", "I-Lower-LBlue.png",
+		"J-Lower-LBlue.png", "K-Lower-LBlue.png", "L-Lower-LBlue.png", "M-Lower-LBlue.png", "N-Lower-LBlue.png", "O-Lower-LBlue.png",
+		"P-Lower-LBlue.png", "Q-Lower-LBlue.png", "R-Lower-LBlue.png", "S-Lower-LBlue.png", "T-Lower-LBlue.png", "U-Lower-LBlue.png",
+		"V-Lower-LBlue.png", "W-Lower-LBlue.png", "X-Lower-LBlue.png", "Y-Lower-LBlue.png", "Z-Lower-LBlue.png", "A-Upper-Gray.png",
+		"B-Upper-Gray.png", "C-Upper-Gray.png", "D-Upper-Gray.png", "E-Upper-Gray.png", "F-Upper-Gray.png", "G-Upper-Gray.png",
+		"H-Upper-Gray.png", "I-Upper-Gray.png", "J-Upper-Gray.png", "K-Upper-Gray.png", "L-Upper-Gray.png", "M-Upper-Gray.png",
+		"N-Upper-Gray.png", "O-Upper-Gray.png", "P-Upper-Gray.png", "Q-Upper-Gray.png", "R-Upper-Gray.png", "S-Upper-Gray.png",
+		"T-Upper-Gray.png", "U-Upper-Gray.png", "V-Upper-Gray.png", "W-Upper-Gray.png", "X-Upper-Gray.png", "Y-Upper-Gray.png",
+		"Z-Upper-Gray.png", "A-Lower-Gray.png", "B-Lower-Gray.png", "C-Lower-Gray.png", "D-Lower-Gray.png", "E-Lower-Gray.png",
+		"F-Lower-Gray.png", "G-Lower-Gray.png", "H-Lower-Gray.png", "I-Lower-Gray.png", "J-Lower-Gray.png", "K-Lower-Gray.png",
+		"L-Lower-Gray.png", "M-Lower-Gray.png", "N-Lower-Gray.png", "O-Lower-Gray.png", "P-Lower-Gray.png", "Q-Lower-Gray.png",
+		"R-Lower-Gray.png", "S-Lower-Gray.png", "T-Lower-Gray.png", "U-Lower-Gray.png", "V-Lower-Gray.png", "W-Lower-Gray.png",
+		"X-Lower-Gray.png", "Y-Lower-Gray.png", "Z-Lower-Gray.png", "Space-Gray.png", "RoundedRectangle-DBlue.png",
+		"RoundedRectangle-LBlue.png", "RoundedRectangle-Gray.png", "Rectangle-LBlue.png", "Rectangle-DBlue.png", "HorizontalPullTab.png",
+		"VerticalPullTab.png",
 	}
 	for _, f := range boundedImgs {
 		a, err := asset.Open(f)
diff --git a/go/src/hearts/img/view/view.go b/go/src/hearts/img/view/view.go
index d45e5c4..c9a09b3 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -233,14 +233,15 @@
 }
 
 // Decides which view of the player's hand to load based on what steps of the round they have completed
+// Likely just for debugging
 func LoadPassOrTakeOrPlay(u *uistate.UIState) {
 	p := u.CurTable.GetPlayers()[u.CurPlayerIndex]
 	if p.GetDoneTaking() || u.CurTable.GetDir() == direction.None {
-		loadPlayView(u)
+		LoadPlayView(u)
 	} else if p.GetDonePassing() {
-		loadTakeView(u)
+		LoadTakeView(u)
 	} else {
-		loadPassView(u)
+		LoadPassView(u)
 	}
 }
 
@@ -285,7 +286,7 @@
 }
 
 // Pass View: Shows player's hand and allows them to pass cards
-func loadPassView(u *uistate.UIState) {
+func LoadPassView(u *uistate.UIState) {
 	u.CurView = uistate.Pass
 	resetImgs(u)
 	resetScene(u)
@@ -299,7 +300,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) {
+func LoadTakeView(u *uistate.UIState) {
 	u.CurView = uistate.Take
 	resetImgs(u)
 	resetScene(u)
@@ -310,53 +311,80 @@
 	if u.Debug {
 		addDebugBar(u)
 	}
+	// animate in take bar
+	reposition.AnimateInTake(u)
 }
 
 // Play View: Shows player's hand and allows them to play cards
-func loadPlayView(u *uistate.UIState) {
+func LoadPlayView(u *uistate.UIState) {
 	u.CurView = uistate.Play
 	resetImgs(u)
 	resetScene(u)
-	addHeader(u)
+	addPlaySlot(u)
 	addHand(u)
+	addPlayHeader(u)
 	if u.Debug {
 		addDebugBar(u)
 	}
+	// animate in play slot if relevant
+	if u.CurTable.WhoseTurn() == u.CurPlayerIndex && u.CurTable.AllDonePassing() {
+		reposition.AnimateInPlay(u)
+	}
 }
 
 func addHeader(u *uistate.UIState) {
 	// adding blue banner
 	headerImage := u.Texs["RoundedRectangle-DBlue.png"]
 	headerPos := coords.MakeVec(0, -10)
-	headerWidth := u.WindowSize.X
-	headerHeight := float32(20)
-	headerDimensions := coords.MakeVec(headerWidth, headerHeight)
+	headerDimensions := coords.MakeVec(u.WindowSize.X, float32(20))
 	u.BackgroundImgs = append(u.BackgroundImgs,
 		texture.MakeImgWithoutAlt(headerImage, headerPos, headerDimensions, u.Eng, u.Scene))
 }
 
-func addHeaderButton(u *uistate.UIState) {
-	// adding blue banner for croupier header
-	headerUnpressed := u.Texs["blue.png"]
-	headerPressed := u.Texs["bluePressed.png"]
+func addPlayHeader(u *uistate.UIState) {
+	// adding blue banner
+	headerImage := u.Texs["Rectangle-DBlue.png"]
 	headerPos := coords.MakeVec(0, 0)
-	headerWidth := u.WindowSize.X
-	var headerHeight float32
-	if 2*u.CardDim.Y < headerWidth/4 {
-		headerHeight = 2 * u.CardDim.Y
-	} else {
-		headerHeight = headerWidth / 4
-	}
-	headerDimensions := coords.MakeVec(headerWidth, headerHeight)
+	headerDimensions := coords.MakeVec(u.WindowSize.X, float32(50))
+	u.BackgroundImgs = append(u.BackgroundImgs,
+		texture.MakeImgWithoutAlt(headerImage, headerPos, headerDimensions, u.Eng, u.Scene))
+	// adding pull tab
+	pullTabImage := u.Texs["HorizontalPullTab.png"]
+	pullTabDim := u.CardDim.DividedBy(2)
+	pullTabPos := headerDimensions.MinusVec(pullTabDim).Minus(u.Padding)
 	u.Buttons = append(u.Buttons,
-		texture.MakeImgWithAlt(headerUnpressed, headerPressed, headerPos, headerDimensions, true, u.Eng, u.Scene))
-	// adding play button
-	playUnpressed := u.Texs["playUnpressed.png"]
-	playPressed := u.Texs["playPressed.png"]
-	playDim := coords.MakeVec(headerHeight, headerHeight/2)
-	playPos := coords.MakeVec((u.WindowSize.X-playDim.X)/2, (u.TopPadding+playDim.Y)/2)
-	play := texture.MakeImgWithAlt(playUnpressed, playPressed, playPos, playDim, true, u.Eng, u.Scene)
-	u.Buttons = append(u.Buttons, play)
+		texture.MakeImgWithoutAlt(pullTabImage, pullTabPos, pullTabDim, u.Eng, u.Scene))
+	// adding text
+	var turnText string
+	playerTurnNum := u.CurTable.WhoseTurn()
+	if playerTurnNum == -1 || !u.CurTable.AllDonePassing() {
+		turnText = "Waiting for other players"
+	} else if playerTurnNum == u.CurPlayerIndex {
+		turnText = "Your turn"
+	} else {
+		name := u.CurTable.GetPlayers()[playerTurnNum].GetName()
+		turnText = name + "'s turn"
+	}
+	color := "DBlue"
+	scaler := float32(4)
+	center := coords.MakeVec(u.WindowSize.X/2, 20)
+	maxWidth := u.WindowSize.X - pullTabDim.X/2
+	nameImgs := texture.MakeStringImgCenterAlign(turnText, color, color, true, center, scaler, maxWidth, u)
+	u.BackgroundImgs = append(u.BackgroundImgs, nameImgs...)
+}
+
+func addPlaySlot(u *uistate.UIState) {
+	// adding blue rectangle
+	blueRectImg := u.Texs["RoundedRectangle-LBlue.png"]
+	blueRectPos := coords.MakeVec(2*u.BottomPadding, 40-u.WindowSize.Y+4*u.BottomPadding)
+	blueRectDim := u.WindowSize.Minus(4 * u.BottomPadding)
+	u.Other = append(u.Other,
+		texture.MakeImgWithoutAlt(blueRectImg, blueRectPos, blueRectDim, u.Eng, u.Scene))
+	// adding drop target
+	dropTargetImg := u.Texs["trickDrop.png"]
+	dropTargetPos := coords.MakeVec(u.WindowSize.X/2-u.CardDim.X/2, -u.Padding)
+	u.DropTargets = append(u.DropTargets,
+		texture.MakeImgWithoutAlt(dropTargetImg, dropTargetPos, u.CardDim, u.Eng, u.Scene))
 }
 
 func addGrayPassBar(u *uistate.UIState) {
@@ -364,7 +392,7 @@
 	grayBarImg := u.Texs["RoundedRectangle-Gray.png"]
 	blueBarImg := u.Texs["RoundedRectangle-LBlue.png"]
 	grayBarPos := coords.MakeVec(2*u.BottomPadding, 40-u.WindowSize.Y+4*u.BottomPadding)
-	grayBarDim := coords.MakeVec(u.WindowSize.X-4*u.BottomPadding, u.WindowSize.Y-4*u.BottomPadding)
+	grayBarDim := u.WindowSize.Minus(4 * u.BottomPadding)
 	u.Other = append(u.Other,
 		texture.MakeImgWithAlt(grayBarImg, blueBarImg, grayBarPos, grayBarDim, true, u.Eng, u.Scene))
 	// adding name
@@ -393,15 +421,15 @@
 	// adding gray bar
 	grayBarImg := u.Texs["RoundedRectangle-Gray.png"]
 	grayBarAlt := u.Texs["RoundedRectangle-LBlue.png"]
-	grayBarPos := coords.MakeVec(2*u.BottomPadding, -30)
 	topOfHand := u.WindowSize.Y - 5*(u.CardDim.Y+u.Padding) - (2 * u.Padding / 5) - u.BottomPadding
 	var grayBarHeight float32
 	if display {
 		grayBarHeight = 105
 	} else {
-		grayBarHeight = topOfHand - u.CardDim.Y
+		grayBarHeight = topOfHand + u.CardDim.Y
 	}
 	grayBarDim := coords.MakeVec(u.WindowSize.X-4*u.BottomPadding, grayBarHeight)
+	grayBarPos := coords.MakeVec(2*u.BottomPadding, -grayBarDim.Y)
 	u.Other = append(u.Other,
 		texture.MakeImgWithAlt(grayBarImg, grayBarAlt, grayBarPos, grayBarDim, display, u.Eng, u.Scene))
 	// adding name
@@ -418,7 +446,7 @@
 	color := "Gray"
 	nameAltColor := "LBlue"
 	awaitingAltColor := "None"
-	center := coords.MakeVec(u.WindowSize.X/2, 5)
+	center := coords.MakeVec(u.WindowSize.X/2, 30-grayBarDim.Y)
 	scaler := float32(3)
 	maxWidth := u.WindowSize.X
 	nameImgs := texture.MakeStringImgCenterAlign(name, color, nameAltColor, display, center, scaler, maxWidth, u)
@@ -437,12 +465,11 @@
 	passedCards := u.CurTable.GetPlayers()[u.CurPlayerIndex].GetPassedTo()
 	if len(passedCards) > 0 {
 		topOfHand := u.WindowSize.Y - 5*(u.CardDim.Y+u.Padding) - (2 * u.Padding / 5) - u.BottomPadding
-		cardY := topOfHand - 3*u.CardDim.Y
 		numCards := float32(3)
 		cardXStart := (u.WindowSize.X - (numCards*u.CardDim.X + (numCards-1)*u.Padding)) / 2
 		for i, c := range passedCards {
 			cardX := cardXStart + float32(i)*(u.Padding+u.CardDim.X)
-			cardPos := coords.MakeVec(cardX, cardY)
+			cardPos := coords.MakeVec(cardX, topOfHand-2*u.CardDim.Y-u.WindowSize.Y/2)
 			c.Move(cardPos, u.CardDim, u.Eng)
 			reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
 			// invisible drop target holding card
diff --git a/go/src/hearts/logic/table/table.go b/go/src/hearts/logic/table/table.go
index b731d99..c3a8f4d 100644
--- a/go/src/hearts/logic/table/table.go
+++ b/go/src/hearts/logic/table/table.go
@@ -11,7 +11,6 @@
 	"hearts/img/direction"
 	"hearts/logic/card"
 	"hearts/logic/player"
-	"log"
 	"math/rand"
 	"sort"
 )
@@ -90,10 +89,27 @@
 
 // Sets the firstplayer variable of t to index
 func (t *Table) SetFirstPlayer(index int) {
-	log.Println("Setting first player to", index)
 	t.firstPlayer = index
 }
 
+// Returns the index of the player whose turn it is, -1 if this cannot be determined at this time
+func (t *Table) WhoseTurn() int {
+	allNil := true
+	for i, c := range t.trick {
+		nextPlayerIndex := (i + 1) % len(t.players)
+		if c != nil {
+			allNil = false
+			if t.trick[nextPlayerIndex] == nil {
+				return nextPlayerIndex
+			}
+		}
+	}
+	if allNil {
+		return t.firstPlayer
+	}
+	return -1
+}
+
 // This function generates a traditional deck of 52 cards, with 13 in each of the four suits
 // Each card has a suit (Club, Diamond, Spade, or Heart)
 // Each card also has a face from Two to Ace (Aces are high in Hearts)
@@ -126,17 +142,7 @@
 
 // Returns whether it is valid for the player at playerIndex to play a card
 func (t *Table) ValidPlayOrder(playerIndex int) bool {
-	if t.firstPlayer == playerIndex {
-		return true
-	}
-	playerBeforeMe := playerIndex - 1
-	if playerBeforeMe < 0 {
-		playerBeforeMe += len(t.players)
-	}
-	if t.trick[playerBeforeMe] == nil {
-		return false
-	}
-	return true
+	return t.WhoseTurn() == playerIndex
 }
 
 // Given a card and the index of its player, returns true if this move was valid based on game logic
@@ -183,7 +189,6 @@
 func (t *Table) AllDonePassing() bool {
 	for _, p := range t.players {
 		if !p.GetDonePassing() {
-			log.Println(p.GetPlayerIndex())
 			return false
 		}
 	}
@@ -315,6 +320,7 @@
 		if t.dir != direction.None {
 			p.SetDonePassing(false)
 			p.SetDoneTaking(false)
+			t.SetFirstPlayer(-1)
 		} else {
 			p.SetDonePassing(true)
 			p.SetDoneTaking(true)
diff --git a/go/src/hearts/syncbase/watch/watch.go b/go/src/hearts/syncbase/watch/watch.go
index a5c81c7..b8e0713 100644
--- a/go/src/hearts/syncbase/watch/watch.go
+++ b/go/src/hearts/syncbase/watch/watch.go
@@ -91,6 +91,8 @@
 		for i, c := range curCards {
 			reposition.AnimateTableCardPass(c, receivingPlayer, i, u)
 		}
+	} else if u.CurView == uistate.Take && u.CurPlayerIndex == receivingPlayer {
+		view.LoadTakeView(u)
 	}
 }
 
@@ -147,9 +149,7 @@
 	}
 	// UI
 	if u.CurView == uistate.Table {
-		c := make(chan bool)
-		go reposition.AnimateTableCardPlay(c, playedCard, playerInt, u)
-		<-c
+		reposition.AnimateTableCardPlay(playedCard, playerInt, u)
 		if trickOver {
 			var trickDir direction.Direction
 			switch recipient {
@@ -163,13 +163,15 @@
 				trickDir = direction.Right
 			}
 			for _, c := range trickCards {
-				ch := make(chan bool)
-				reposition.AnimateTableCardTakeTrick(ch, c, trickDir, u)
-				<-ch
+				reposition.AnimateTableCardTakeTrick(c, trickDir, u)
 			}
 		}
-	} else if u.CurView == uistate.Play && roundOver {
-		view.LoadScoreView(winners, u)
+	} else if u.CurView == uistate.Play {
+		if roundOver {
+			view.LoadScoreView(winners, u)
+		} else if u.CurPlayerIndex != playerInt {
+			view.LoadPlayView(u)
+		}
 	}
 	// logic
 	if len(winners) > 0 {
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index ccc1d9f..5edd64b 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -122,7 +122,7 @@
 						finalX := blueBanner.GetInitial().X
 						finalY := pullTab.GetInitial().Y + pullTab.GetDimensions().Y - blueBanner.GetDimensions().Y
 						finalPos := coords.MakeVec(finalX, finalY)
-						reposition.AnimateImageMovement(blueBanner, finalPos, blueBanner.GetDimensions())
+						reposition.AnimateImageNoChannel(blueBanner, finalPos, blueBanner.GetDimensions())
 					}
 				}
 			} else if u.Buttons[1] == buttonList[0] {
@@ -191,13 +191,15 @@
 		}
 	} else if u.CurImg != nil && touchingStaticImg(t, u.Other[0], u) {
 		ch := make(chan bool)
-		go passCards(ch, u.CurPlayerIndex, u)
-		success := <-ch
-		if !success {
-			fmt.Println("Invalid pass")
-		} else {
-			view.LoadPassOrTakeOrPlay(u)
-		}
+		success := passCards(ch, u.CurPlayerIndex, u)
+		go func() {
+			<-ch
+			if !success {
+				fmt.Println("Invalid pass")
+			} else {
+				view.LoadTakeView(u)
+			}
+		}()
 	}
 	u.CurCard = nil
 	u.CurImg = nil
@@ -238,13 +240,15 @@
 		}
 		if doneTaking {
 			ch := make(chan bool)
-			go takeCards(ch, u.CurPlayerIndex, u)
-			success := <-ch
-			if !success {
-				fmt.Println("Invalid take")
-			} else {
-				view.LoadPassOrTakeOrPlay(u)
-			}
+			success := takeCards(ch, u.CurPlayerIndex, u)
+			go func() {
+				<-ch
+				if !success {
+					fmt.Println("Invalid take")
+				} else {
+					view.LoadPlayView(u)
+				}
+			}()
 		}
 	}
 	u.CurCard = nil
@@ -256,22 +260,12 @@
 	if len(buttonList) > 0 {
 		if u.Debug {
 			if u.Buttons[0] == buttonList[0] {
-				pressButton(buttonList[0], u)
-				err := playCard(u.CurPlayerIndex, u)
-				if err != "" {
-					fmt.Println(err)
-				}
+				u.CurImg = u.Buttons[0]
 			} else if u.Buttons[1] == buttonList[0] {
 				view.LoadTableView(u)
 			} else if u.Buttons[2] == buttonList[0] {
 				view.LoadPassOrTakeOrPlay(u)
 			}
-		} else {
-			pressButton(buttonList[0], u)
-			err := playCard(u.CurPlayerIndex, u)
-			if err != "" {
-				fmt.Println(err)
-			}
 		}
 	}
 }
@@ -290,9 +284,19 @@
 			// add card back to hand
 			reposition.ResetCardPosition(u.CurCard, u.Eng)
 			reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
+		} else {
+			ch := make(chan bool)
+			err := playCard(ch, u.CurPlayerIndex, u)
+			go func() {
+				<-ch
+				if err != "" {
+					fmt.Println(err)
+				} else {
+					view.LoadPlayView(u)
+				}
+			}()
 		}
 	}
-	unpressButtons(u)
 	u.CurCard = nil
 }
 
@@ -330,7 +334,7 @@
 }
 
 // returns true if pass was successful
-func passCards(ch chan bool, playerId int, u *uistate.UIState) {
+func passCards(ch chan bool, playerId int, u *uistate.UIState) bool {
 	cardsPassed := make([]*card.Card, 0)
 	dropsToReset := make([]*staticimg.StaticImg, 0)
 	for _, d := range u.DropTargets {
@@ -358,16 +362,13 @@
 		for _, i := range imgs {
 			u.Eng.SetSubTex(i.GetNode(), blankTex)
 		}
-		ch2 := make(chan bool)
-		go reposition.AnimateHandCardPass(ch2, u.Other, cardsPassed, u)
-		<-ch2
-		ch <- true
-	} else {
-		ch <- false
+		reposition.AnimateHandCardPass(ch, u.Other, cardsPassed, u)
+		return true
 	}
+	return false
 }
 
-func takeCards(ch chan bool, playerId int, u *uistate.UIState) {
+func takeCards(ch chan bool, playerId int, u *uistate.UIState) bool {
 	player := u.CurTable.GetPlayers()[playerId]
 	passedCards := player.GetPassedTo()
 	if len(passedCards) == 3 {
@@ -375,17 +376,13 @@
 		for !success {
 			success = gamelog.LogTake(u)
 		}
-		// UI
-		ch2 := make(chan bool)
-		go reposition.AnimateHandCardTake(ch2, u.Other, u)
-		<-ch2
-		ch <- true
-	} else {
-		ch <- false
+		reposition.AnimateHandCardTake(ch, u.Other, u)
+		return true
 	}
+	return false
 }
 
-func playCard(playerId int, u *uistate.UIState) string {
+func playCard(ch chan bool, playerId int, u *uistate.UIState) string {
 	c := u.DropTargets[0].GetCardHere()
 	if c != nil {
 		// checks to make sure that:
@@ -410,9 +407,7 @@
 		for !success {
 			success = gamelog.LogPlay(u, c)
 		}
-		ch := make(chan bool)
 		reposition.AnimateHandCardPlay(ch, c, u)
-		<-ch
 		return ""
 	}
 	return "Invalid play: No card has been played"