Merge "Changed pass view to hopefully be more intuitive"
diff --git a/go/src/hearts/assets/AcrossArrowBlue.png b/go/src/hearts/assets/AcrossArrowBlue.png
new file mode 100644
index 0000000..f569f18
--- /dev/null
+++ b/go/src/hearts/assets/AcrossArrowBlue.png
Binary files differ
diff --git a/go/src/hearts/assets/AcrossArrowGray.png b/go/src/hearts/assets/AcrossArrowGray.png
new file mode 100644
index 0000000..de97530
--- /dev/null
+++ b/go/src/hearts/assets/AcrossArrowGray.png
Binary files differ
diff --git a/go/src/hearts/assets/LeftArrowBlue.png b/go/src/hearts/assets/LeftArrowBlue.png
new file mode 100644
index 0000000..f949609
--- /dev/null
+++ b/go/src/hearts/assets/LeftArrowBlue.png
Binary files differ
diff --git a/go/src/hearts/assets/LeftArrowGray.png b/go/src/hearts/assets/LeftArrowGray.png
new file mode 100644
index 0000000..dddac1a
--- /dev/null
+++ b/go/src/hearts/assets/LeftArrowGray.png
Binary files differ
diff --git a/go/src/hearts/assets/PassPressed.png b/go/src/hearts/assets/PassPressed.png
new file mode 100644
index 0000000..c5a5a28
--- /dev/null
+++ b/go/src/hearts/assets/PassPressed.png
Binary files differ
diff --git a/go/src/hearts/assets/PassUnpressed.png b/go/src/hearts/assets/PassUnpressed.png
new file mode 100644
index 0000000..a90664e
--- /dev/null
+++ b/go/src/hearts/assets/PassUnpressed.png
Binary files differ
diff --git a/go/src/hearts/assets/QuitPressed.png b/go/src/hearts/assets/QuitPressed.png
index f42be9b..2f45344 100644
--- a/go/src/hearts/assets/QuitPressed.png
+++ b/go/src/hearts/assets/QuitPressed.png
Binary files differ
diff --git a/go/src/hearts/assets/QuitUnpressed.png b/go/src/hearts/assets/QuitUnpressed.png
index 47deba6..6d62380 100644
--- a/go/src/hearts/assets/QuitUnpressed.png
+++ b/go/src/hearts/assets/QuitUnpressed.png
Binary files differ
diff --git a/go/src/hearts/assets/RightArrowBlue.png b/go/src/hearts/assets/RightArrowBlue.png
new file mode 100644
index 0000000..b147d7e
--- /dev/null
+++ b/go/src/hearts/assets/RightArrowBlue.png
Binary files differ
diff --git a/go/src/hearts/assets/RightArrowGray.png b/go/src/hearts/assets/RightArrowGray.png
new file mode 100644
index 0000000..59866a0
--- /dev/null
+++ b/go/src/hearts/assets/RightArrowGray.png
Binary files differ
diff --git a/go/src/hearts/assets/SitSpotPressed.png b/go/src/hearts/assets/SitSpotPressed.png
index b4ada5f..c11470e 100644
--- a/go/src/hearts/assets/SitSpotPressed.png
+++ b/go/src/hearts/assets/SitSpotPressed.png
Binary files differ
diff --git a/go/src/hearts/assets/SitSpotUnpressed.png b/go/src/hearts/assets/SitSpotUnpressed.png
index 0991f49..8943bb6 100644
--- a/go/src/hearts/assets/SitSpotUnpressed.png
+++ b/go/src/hearts/assets/SitSpotUnpressed.png
Binary files differ
diff --git a/go/src/hearts/assets/StartGray.png b/go/src/hearts/assets/StartGray.png
index aced4e1..89e1dee 100644
--- a/go/src/hearts/assets/StartGray.png
+++ b/go/src/hearts/assets/StartGray.png
Binary files differ
diff --git a/go/src/hearts/assets/WatchSpotPressed.png b/go/src/hearts/assets/WatchSpotPressed.png
index 6060786..c51cc49 100644
--- a/go/src/hearts/assets/WatchSpotPressed.png
+++ b/go/src/hearts/assets/WatchSpotPressed.png
Binary files differ
diff --git a/go/src/hearts/assets/WatchSpotUnpressed.png b/go/src/hearts/assets/WatchSpotUnpressed.png
index 37b446c..67413e5 100644
--- a/go/src/hearts/assets/WatchSpotUnpressed.png
+++ b/go/src/hearts/assets/WatchSpotUnpressed.png
Binary files differ
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index 4f32f36..0e7a6e5 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -179,19 +179,14 @@
 }
 
 // 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 {
+func AnimateHandCardPass(ch chan bool, animImages []*staticimg.StaticImg, u *uistate.UIState) {
+	for counter, i := range animImages {
 		dims := i.GetDimensions()
 		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y-u.WindowSize.Y)
-		AnimateImageNoChannel(i, to, dims, u)
-	}
-	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, u)
+		if counter < len(animImages)-1 {
+			AnimateImageNoChannel(i, to, dims, u)
 		} else {
-			animateCardMovement(ch, c, to, dims, u)
+			animateImageMovement(ch, i, to, dims, u)
 		}
 	}
 }
@@ -211,18 +206,21 @@
 // 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()
 		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y)
 		AnimateImageNoChannel(i, to, dims, u)
 	}
-	if !u.SequentialPhases || u.CurTable.AllDonePassing() {
-		for _, c := range passedCards {
-			dims := c.GetDimensions()
-			to := coords.MakeVec(c.GetCurrent().X, c.GetCurrent().Y+u.WindowSize.Y)
-			animateCardNoChannel(c, to, dims, u)
-		}
+}
+
+// Animation to bring in the pass slot
+func AnimateInPass(u *uistate.UIState) {
+	imgs := append(u.Other, u.DropTargets...)
+	imgs = append(imgs, u.Buttons["pass"])
+	for _, i := range imgs {
+		dims := i.GetDimensions()
+		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y)
+		AnimateImageNoChannel(i, to, dims, u)
 	}
 }
 
@@ -238,13 +236,16 @@
 		BringNodeToFront(img.GetNode(), u)
 	}
 	imgs := []*staticimg.StaticImg{u.BackgroundImgs[0], u.DropTargets[0]}
-	for _, i := range imgs {
+	for counter, i := range imgs {
 		dims := i.GetDimensions()
 		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y-u.WindowSize.Y)
-		AnimateImageNoChannel(i, to, dims, u)
+		if counter == len(imgs)-1 {
+			animateImageMovement(ch, i, to, dims, u)
+		} else {
+			AnimateImageNoChannel(i, to, dims, u)
+		}
+
 	}
-	to := coords.MakeVec(animCard.GetCurrent().X, animCard.GetCurrent().Y-u.WindowSize.Y)
-	animateCardMovement(ch, animCard, to, animCard.GetDimensions(), u)
 }
 
 // Animation to bring in the play slot when app is in the hand view and it is the player's turn
@@ -281,17 +282,10 @@
 	topOfBanner := u.WindowSize.Y - 4*u.CardDim.Y - 5*u.Padding - u.BottomPadding - 40
 	tableImgs := make([]*staticimg.StaticImg, 0)
 	bannerImgs := make([]*staticimg.StaticImg, 0)
-	cards := make([]*card.Card, 0)
 	bannerImgs = append(bannerImgs, u.Other...)
 	bannerImgs = append(bannerImgs, u.Buttons["toggleSplit"])
 	tableImgs = append(tableImgs, u.DropTargets...)
 	tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers]...)
-	cards = append(cards, u.TableCards...)
-	for _, card := range cards {
-		from := card.GetCurrent()
-		to := coords.MakeVec(from.X, from.Y+topOfBanner)
-		animateCardNoChannel(card, to, card.GetDimensions(), u)
-	}
 	for _, img := range tableImgs {
 		from := img.GetCurrent()
 		to := coords.MakeVec(from.X, from.Y+topOfBanner)
@@ -326,17 +320,10 @@
 	topOfBanner := u.WindowSize.Y - 4*u.CardDim.Y - 5*u.Padding - u.BottomPadding - 40
 	tableImgs := make([]*staticimg.StaticImg, 0)
 	bannerImgs := make([]*staticimg.StaticImg, 0)
-	cards := make([]*card.Card, 0)
 	bannerImgs = append(bannerImgs, u.Other...)
 	bannerImgs = append(bannerImgs, u.Buttons["toggleSplit"])
 	tableImgs = append(tableImgs, u.DropTargets...)
 	tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers]...)
-	cards = append(cards, u.TableCards...)
-	for _, card := range cards {
-		from := card.GetCurrent()
-		to := coords.MakeVec(from.X, from.Y-topOfBanner)
-		animateCardNoChannel(card, to, card.GetDimensions(), u)
-	}
 	for _, img := range tableImgs {
 		from := img.GetCurrent()
 		to := coords.MakeVec(from.X, from.Y-topOfBanner)
@@ -417,8 +404,16 @@
 			newVec := curXY.PlusVec(XYStep)
 			dimVec := curDim.PlusVec(dimStep)
 			animImage.Move(newVec, dimVec, eng)
+			card := animImage.GetCardHere()
+			if card != nil {
+				card.Move(newVec, dimVec, eng)
+			}
 		} else if iteration == animationFrameCount {
 			animImage.Move(endPos, endDim, eng)
+			card := animImage.GetCardHere()
+			if card != nil {
+				card.Move(endPos, endDim, eng)
+			}
 			c <- true
 		}
 	})
@@ -439,8 +434,16 @@
 			newVec := curXY.PlusVec(XYStep)
 			dimVec := curDim.PlusVec(dimStep)
 			animImage.Move(newVec, dimVec, eng)
+			card := animImage.GetCardHere()
+			if card != nil {
+				card.Move(newVec, dimVec, eng)
+			}
 		} else if iteration == animationFrameCount {
 			animImage.Move(endPos, endDim, eng)
+			card := animImage.GetCardHere()
+			if card != nil {
+				card.Move(endPos, endDim, eng)
+			}
 		}
 	})
 }
diff --git a/go/src/hearts/img/texture/texture.go b/go/src/hearts/img/texture/texture.go
index fd96e76..aacf862 100644
--- a/go/src/hearts/img/texture/texture.go
+++ b/go/src/hearts/img/texture/texture.go
@@ -275,6 +275,8 @@
 		"NewRoundPressed.png", "NewRoundUnpressed.png", "JoinGamePressed.png", "JoinGameUnpressed.png", "Period.png",
 		"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",
 	}
 	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 bb5c898..cbdb649 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:            false,
+		Debug:            true,
 		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 29d26bd..fcd4814 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -28,11 +28,13 @@
 
 // Arrange view: For seating players
 func LoadArrangeView(u *uistate.UIState) {
-	u.CurView = uistate.Arrange
-	<-time.After(1 * time.Second)
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
+	u.CurView = uistate.Arrange
 	addHeader(u)
 	watchImg := u.Texs["WatchSpotUnpressed.png"]
 	watchAlt := u.Texs["WatchSpotPressed.png"]
@@ -58,19 +60,26 @@
 	quitPos := coords.MakeVec(u.Padding, u.TopPadding+10)
 	u.Buttons["exit"] = texture.MakeImgWithAlt(quitImg, quitAlt, quitPos, quitDim, true, u)
 	if u.IsOwner {
-		startImg := u.Texs["StartGray.png"]
-		startAlt := u.Texs["StartBlue.png"]
+		startImg := u.Texs["StartBlue.png"]
+		startAlt := u.Texs["StartBluePressed.png"]
 		startDim := coords.MakeVec(2*u.CardDim.X, u.CardDim.Y)
 		startPos := u.WindowSize.MinusVec(startDim).Minus(u.BottomPadding)
-		display := !u.CurTable.AllReadyForNewRound()
-		u.Buttons["start"] = texture.MakeImgWithAlt(startImg, startAlt, startPos, startDim, display, u)
+		display := u.CurTable.AllReadyForNewRound()
+		u.Buttons["start"] = texture.MakeImgWithAlt(startImg, startAlt, startPos, startDim, true, u)
+		var emptyTex sprite.SubTex
+		if !display {
+			u.Eng.SetSubTex(u.Buttons["start"].GetNode(), emptyTex)
+		}
 	}
 }
 
 // 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) {
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
 	center := u.WindowSize.DividedBy(2)
@@ -84,10 +93,13 @@
 
 // Discovery view: Displays a menu of possible games to join
 func LoadDiscoveryView(u *uistate.UIState) {
-	u.CurView = uistate.Discovery
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
+	u.CurView = uistate.Discovery
 	newGameImg := u.Texs["NewGameUnpressed.png"]
 	newGameAlt := u.Texs["NewGamePressed.png"]
 	newGameDim := coords.MakeVec(2*u.CardDim.X, u.CardDim.Y)
@@ -128,10 +140,13 @@
 
 // Table View: Displays the table. Intended for public devices
 func LoadTableView(u *uistate.UIState) {
-	u.CurView = uistate.Table
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
+	u.CurView = uistate.Table
 	scaler := float32(6)
 	maxWidth := 4 * u.TableCardDim.X
 	// adding four drop targets for trick
@@ -354,7 +369,6 @@
 }
 
 // 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 {
@@ -368,10 +382,13 @@
 
 // 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) {
-	u.CurView = uistate.Score
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
+	u.CurView = uistate.Score
 	addHeader(u)
 	addScoreViewHeaderText(u)
 	addPlayerScores(roundScores, u)
@@ -380,25 +397,32 @@
 
 // Pass View: Shows player's hand and allows them to pass cards
 func LoadPassView(u *uistate.UIState) {
-	u.CurView = uistate.Pass
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
+	u.CurView = uistate.Pass
 	addHeader(u)
 	addGrayPassBar(u)
-	addPassDrops(u)
+	//addPassDrops(u)
 	addHand(u)
 	if u.Debug {
 		addDebugBar(u)
 	}
+	reposition.AnimateInPass(u)
 }
 
 // Take View: Shows player's hand and allows them to take the cards that have been passed to them
 func LoadTakeView(u *uistate.UIState) {
-	u.CurView = uistate.Take
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
+	u.CurView = uistate.Take
 	addHeader(u)
 	addGrayTakeBar(u)
 	addHand(u)
@@ -412,11 +436,13 @@
 
 // Play View: Shows player's hand and allows them to play cards
 func LoadPlayView(u *uistate.UIState) {
-	u.CurView = uistate.Play
-	fmt.Println("In play view")
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
+	u.CurView = uistate.Play
 	addPlaySlot(u)
 	addHand(u)
 	addPlayHeader(getTurnText(u), false, u)
@@ -437,11 +463,13 @@
 }
 
 func LoadSplitView(reloading bool, u *uistate.UIState) {
-	u.CurView = uistate.Split
-	fmt.Println("In split view")
-	reposition.ResetAnims(u)
+	if len(u.AnimChans) > 0 {
+		reposition.ResetAnims(u)
+		<-time.After(time.Second)
+	}
 	resetImgs(u)
 	resetScene(u)
+	u.CurView = uistate.Split
 	addPlayHeader(getTurnText(u), !reloading, u)
 	addSplitViewPlayerIcons(!reloading, u)
 	SetNumTricksHand(u)
@@ -536,8 +564,8 @@
 		dropTargetY -= topOfBanner
 	}
 	dropTargetPos := coords.MakeVec(dropTargetX, dropTargetY)
-	u.DropTargets = append(u.DropTargets,
-		texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u))
+	d := texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u)
+	u.DropTargets = append(u.DropTargets, d)
 	// first player icon
 	playerIconImage := uistate.GetAvatar(u.CurPlayerIndex, u)
 	u.BackgroundImgs = append(u.BackgroundImgs,
@@ -548,6 +576,7 @@
 		texture.PopulateCardImage(dropCard, u)
 		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
+		d.SetCardHere(dropCard)
 		u.TableCards = append(u.TableCards, dropCard)
 	}
 	// second drop target
@@ -557,8 +586,8 @@
 	}
 	dropTargetX = splitWindowSize.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))
+	d = texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u)
+	u.DropTargets = append(u.DropTargets, d)
 	// second player icon
 	playerIconImage = uistate.GetAvatar((u.CurPlayerIndex+1)%u.NumPlayers, u)
 	u.BackgroundImgs = append(u.BackgroundImgs,
@@ -569,6 +598,7 @@
 		texture.PopulateCardImage(dropCard, u)
 		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
+		d.SetCardHere(dropCard)
 		u.TableCards = append(u.TableCards, dropCard)
 	}
 	// third drop target
@@ -578,8 +608,8 @@
 		dropTargetY -= topOfBanner
 	}
 	dropTargetPos = coords.MakeVec(dropTargetX, dropTargetY)
-	u.DropTargets = append(u.DropTargets,
-		texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u))
+	d = texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u)
+	u.DropTargets = append(u.DropTargets, d)
 	// third player icon
 	playerIconImage = uistate.GetAvatar((u.CurPlayerIndex+2)%u.NumPlayers, u)
 	u.BackgroundImgs = append(u.BackgroundImgs,
@@ -590,6 +620,7 @@
 		texture.PopulateCardImage(dropCard, u)
 		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
+		d.SetCardHere(dropCard)
 		u.TableCards = append(u.TableCards, dropCard)
 	}
 	// fourth drop target
@@ -599,8 +630,8 @@
 	}
 	dropTargetX = splitWindowSize.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))
+	d = texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u)
+	u.DropTargets = append(u.DropTargets, d)
 	// fourth player icon
 	playerIconImage = uistate.GetAvatar((u.CurPlayerIndex+3)%u.NumPlayers, u)
 	u.BackgroundImgs = append(u.BackgroundImgs,
@@ -611,6 +642,7 @@
 		texture.PopulateCardImage(dropCard, u)
 		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
+		d.SetCardHere(dropCard)
 		u.TableCards = append(u.TableCards, dropCard)
 	}
 }
@@ -688,28 +720,61 @@
 	// adding gray bar
 	grayBarImg := u.Texs["RoundedRectangle-Gray.png"]
 	blueBarImg := u.Texs["RoundedRectangle-LBlue.png"]
-	grayBarDim := u.WindowSize.Minus(4 * u.BottomPadding)
-	grayBarPos := coords.MakeVec(2*u.BottomPadding, 40-grayBarDim.Y+u.TopPadding)
+	topOfHand := u.WindowSize.Y - 5*(u.CardDim.Y+u.Padding) - (2 * u.Padding / 5) - u.BottomPadding
+	grayBarDim := coords.MakeVec(u.WindowSize.X-4*u.BottomPadding, topOfHand+u.CardDim.Y)
+	grayBarPos := coords.MakeVec(2*u.BottomPadding, -u.WindowSize.Y-20)
 	u.Other = append(u.Other,
 		texture.MakeImgWithAlt(grayBarImg, blueBarImg, grayBarPos, grayBarDim, true, u))
 	// adding name
 	var receivingPlayer int
+	var arrowImg sprite.SubTex
+	var arrowAlt sprite.SubTex
 	switch u.CurTable.GetDir() {
 	case direction.Right:
 		receivingPlayer = (u.CurPlayerIndex + 3) % u.NumPlayers
+		arrowImg = u.Texs["RightArrowGray.png"]
+		arrowAlt = u.Texs["RightArrowBlue.png"]
 	case direction.Left:
 		receivingPlayer = (u.CurPlayerIndex + 1) % u.NumPlayers
+		arrowImg = u.Texs["LeftArrowGray.png"]
+		arrowAlt = u.Texs["LeftArrowBlue.png"]
 	case direction.Across:
 		receivingPlayer = (u.CurPlayerIndex + 2) % u.NumPlayers
+		arrowImg = u.Texs["AcrossArrowGray.png"]
+		arrowAlt = u.Texs["AcrossArrowBlue.png"]
 	}
+	arrowDim := u.CardDim
 	name := uistate.GetName(receivingPlayer, u)
 	color := "Gray"
 	altColor := "LBlue"
-	center := coords.MakeVec(u.WindowSize.X/2, u.TopPadding+5)
+	center := coords.MakeVec(u.WindowSize.X/2-arrowDim.X/2, 20-u.WindowSize.Y)
 	scaler := float32(3)
-	maxWidth := grayBarDim.X - 2*u.Padding
-	nameImgs := texture.MakeStringImgCenterAlign(name, color, altColor, true, center, scaler, maxWidth, u)
+	maxWidth := grayBarDim.X - 3*u.Padding - arrowDim.X
+	nameImgs := texture.MakeStringImgCenterAlign(fmt.Sprintf("Pass to %s", name), color, altColor, true, center, scaler, maxWidth, u)
 	u.Other = append(u.Other, nameImgs...)
+	imgBeforeArrow := u.Other[len(u.Other)-1]
+	ibaDim := imgBeforeArrow.GetDimensions()
+	ibaPos := imgBeforeArrow.GetCurrent()
+	arrowPos := coords.MakeVec(ibaPos.X+ibaDim.X+u.Padding, ibaPos.Y+ibaDim.Y/2-arrowDim.Y/2)
+	u.Other = append(u.Other,
+		texture.MakeImgWithAlt(arrowImg, arrowAlt, arrowPos, arrowDim, true, u))
+	numDrops := 3
+	dropXStart := (u.WindowSize.X - (float32(numDrops)*u.CardDim.X + (float32(numDrops)-1)*u.Padding)) / 2
+	dropImg := u.Texs["trickDrop.png"]
+	for i := 0; i < numDrops; i++ {
+		dropX := dropXStart + float32(i)*(u.Padding+u.CardDim.X)
+		dropPos := coords.MakeVec(dropX, topOfHand-u.Padding-u.WindowSize.Y-20)
+		d := texture.MakeImgWithoutAlt(dropImg, dropPos, u.CardDim, u)
+		u.DropTargets = append(u.DropTargets, d)
+	}
+	passImg := u.Texs["PassUnpressed.png"]
+	passAlt := u.Texs["PassPressed.png"]
+	passDim := coords.MakeVec(2*u.CardDim.X, 2*u.CardDim.Y/3)
+	passPos := coords.MakeVec((u.WindowSize.X-passDim.X)/2, topOfHand-2*u.Padding-u.WindowSize.Y-20-passDim.Y)
+	b := texture.MakeImgWithAlt(passImg, passAlt, passPos, passDim, true, u)
+	var emptyTex sprite.SubTex
+	u.Eng.SetSubTex(b.GetNode(), emptyTex)
+	u.Buttons["pass"] = b
 }
 
 func addGrayTakeBar(u *uistate.UIState) {
diff --git a/go/src/hearts/sync/client.go b/go/src/hearts/sync/client.go
index 63f57fe..63d6442 100644
--- a/go/src/hearts/sync/client.go
+++ b/go/src/hearts/sync/client.go
@@ -95,7 +95,7 @@
 }
 
 // Joins gamelog syncgroup
-func JoinLogSyncgroup(ch chan bool, logName string, u *uistate.UIState) {
+func JoinLogSyncgroup(logName string, u *uistate.UIState) bool {
 	fmt.Println("Joining gamelog syncgroup")
 	u.IsOwner = false
 	app := u.Service.App(AppName)
@@ -105,13 +105,13 @@
 	_, err := logSg.Join(u.Ctx, myInfoJoiner)
 	if err != nil {
 		fmt.Println("SYNCGROUP JOIN ERROR: ", err)
-		ch <- false
+		return false
 	} else {
 		fmt.Println("Syncgroup joined")
 		if u.LogSG != logName {
 			resetGame(logName, false, u)
 		}
-		ch <- true
+		return true
 	}
 }
 
diff --git a/go/src/hearts/sync/server.go b/go/src/hearts/sync/server.go
index 03887be..38ed5f4 100644
--- a/go/src/hearts/sync/server.go
+++ b/go/src/hearts/sync/server.go
@@ -116,7 +116,7 @@
 }
 
 // Creates a new gamelog syncgroup
-func CreateLogSyncgroup(ch chan string, u *uistate.UIState) {
+func CreateLogSyncgroup(u *uistate.UIState) (string, string) {
 	fmt.Println("Creating Log Syncgroup")
 	u.IsOwner = true
 	// Generate random gameID information to advertise this game
@@ -131,7 +131,6 @@
 	if err != nil {
 		fmt.Println("WE HAVE A HUGE PROBLEM:", err)
 	}
-	ch <- string(value)
 	// Create gamelog syncgroup
 	logSGName := fmt.Sprintf("%s/croupier/%s/%%%%sync/gaming-%d", MountPoint, SBName, gameID)
 	allAccess := access.AccessList{In: []security.BlessingPattern{"..."}}
@@ -163,21 +162,21 @@
 		_, err2 := logSG.Join(u.Ctx, myInfoCreator)
 		if err2 != nil {
 			fmt.Println("SYNCGROUP JOIN ERROR: ", err2)
-			ch <- ""
+			return string(value), ""
 		} else {
-			ch <- logSGName
+			return string(value), logSGName
 		}
 	} else {
 		fmt.Println("Syncgroup created")
 		if logSGName != u.LogSG {
 			resetGame(logSGName, true, u)
 		}
-		ch <- logSGName
+		return string(value), logSGName
 	}
 }
 
 // Creates a new user settings syncgroup
-func CreateSettingsSyncgroup(ch chan string, u *uistate.UIState) {
+func CreateSettingsSyncgroup(u *uistate.UIState) string {
 	fmt.Println("Creating Settings Syncgroup")
 	allAccess := access.AccessList{In: []security.BlessingPattern{"..."}}
 	permissions := access.Permissions{
@@ -209,13 +208,13 @@
 		_, err2 := settingsSG.Join(u.Ctx, myInfoCreator)
 		if err2 != nil {
 			fmt.Println("SYNCGROUP JOIN ERROR: ", err2)
-			ch <- ""
+			return ""
 		} else {
-			ch <- settingsSGName
+			return settingsSGName
 		}
 	} else {
 		fmt.Println("Syncgroup created")
-		ch <- settingsSGName
+		return settingsSGName
 	}
 }
 
diff --git a/go/src/hearts/sync/util.go b/go/src/hearts/sync/util.go
index 8c6b586..b1da39f 100644
--- a/go/src/hearts/sync/util.go
+++ b/go/src/hearts/sync/util.go
@@ -8,12 +8,12 @@
 
 const (
 	// switch back to my mountpoint with the following code:
-	MountPoint = "users/emshack@google.com"
-	//MountPoint        = "/192.168.86.254:8101"
-	UserID            = 2222
+	//MountPoint = "users/emshack@google.com"
+	MountPoint        = "/192.168.86.254:8101"
+	UserID            = 1111
 	UserColor         = 16777215
-	UserAvatar        = "player1.jpeg"
-	UserName          = "Bob"
+	UserAvatar        = "player0.jpeg"
+	UserName          = "Alice"
 	SBName            = "syncbase"
 	AppName           = "app"
 	DbName            = "db"
diff --git a/go/src/hearts/sync/watch.go b/go/src/hearts/sync/watch.go
index 5e489f7..e458cf4 100644
--- a/go/src/hearts/sync/watch.go
+++ b/go/src/hearts/sync/watch.go
@@ -362,12 +362,8 @@
 	if u.CurTable.AllReadyForNewRound() && u.IsOwner {
 		if u.CurView == uistate.Arrange {
 			b := u.Buttons["start"]
-			if !b.GetDisplayingImage() {
-				b.SetImage(b.GetAlt())
-				b.SetAlt(u.Texs["StartBluePressed.png"])
-				u.Eng.SetSubTex(b.GetNode(), b.GetImage())
-				b.SetDisplayingImage(true)
-			}
+			u.Eng.SetSubTex(b.GetNode(), b.GetImage())
+			b.SetDisplayingImage(true)
 			if u.SGChan != nil {
 				u.SGChan <- true
 				u.SGChan = nil
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index f2cc3aa..f66ae14 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -14,7 +14,6 @@
 	"golang.org/x/mobile/event/touch"
 	"golang.org/x/mobile/exp/sprite"
 
-	"hearts/img/coords"
 	"hearts/img/reposition"
 	"hearts/img/staticimg"
 	"hearts/img/uistate"
@@ -51,9 +50,7 @@
 	case uistate.Table:
 		switch t.Type {
 		case touch.TypeBegin:
-			if u.Debug {
-				beginClickTable(t, u)
-			}
+			beginClickTable(t, u)
 		}
 	case uistate.Pass:
 		switch t.Type {
@@ -138,13 +135,8 @@
 	pressed := unpressButtons(u)
 	for _, button := range pressed {
 		if button == u.Buttons["newGame"] {
-			logCh := make(chan string)
-			settingsCh := make(chan string)
-			go sync.CreateLogSyncgroup(logCh, u)
-			go sync.CreateSettingsSyncgroup(settingsCh, u)
-			gameStartData := <-logCh
-			logName := <-logCh
-			settingsName := <-settingsCh
+			gameStartData, logName := sync.CreateLogSyncgroup(u)
+			settingsName := sync.CreateSettingsSyncgroup(u)
 			if logName != "" && settingsName != "" {
 				sync.LogSettingsName(settingsName, u)
 				u.ScanChan <- true
@@ -156,13 +148,10 @@
 		} else {
 			for _, b := range u.Buttons {
 				if button == b {
-					joinLogDone := make(chan bool)
 					logAddr := b.GetInfo()
-					go sync.JoinLogSyncgroup(joinLogDone, logAddr, u)
-					if success := <-joinLogDone; success {
-						settingsCh := make(chan string)
-						go sync.CreateSettingsSyncgroup(settingsCh, u)
-						sgName := <-settingsCh
+					success := sync.JoinLogSyncgroup(logAddr, u)
+					if success {
+						sgName := sync.CreateSettingsSyncgroup(u)
 						if sgName != "" {
 							sync.LogSettingsName(sgName, u)
 						}
@@ -187,7 +176,7 @@
 			if u.CurTable.AllReadyForNewRound() {
 				pressButton(b, u)
 			}
-		} else if u.CurPlayerIndex < 0 {
+		} else if u.CurPlayerIndex < 0 || u.Debug {
 			for _, button := range u.Buttons {
 				if b == button {
 					pressButton(b, u)
@@ -232,17 +221,15 @@
 			}
 		} else {
 			for key, button := range u.Buttons {
-				if b == button && u.CurPlayerIndex < 0 {
+				if b == button && (u.CurPlayerIndex < 0 || u.Debug) {
 					if key == "joinTable" {
 						u.CurPlayerIndex = 4
 						sync.LogPlayerNum(u)
 					} else {
 						playerNum := strings.Split(key, "-")[1]
-						if u.CurPlayerIndex < 0 {
-							u.CurPlayerIndex, _ = strconv.Atoi(playerNum)
-							sync.LogReady(u)
-							sync.LogPlayerNum(u)
-						}
+						u.CurPlayerIndex, _ = strconv.Atoi(playerNum)
+						sync.LogReady(u)
+						sync.LogPlayerNum(u)
 					}
 				}
 			}
@@ -268,51 +255,21 @@
 			view.LoadTableView(u)
 		} else if b == u.Buttons["hand"] {
 			view.LoadPassOrTakeOrPlay(u)
-		} else if b == u.Buttons["dragPass"] {
-			if b.GetDisplayingImage() {
-				u.CurImg = b
-				for _, img := range u.Other {
-					u.Eng.SetSubTex(img.GetNode(), img.GetAlt())
-					img.SetDisplayingImage(false)
-				}
-				blueBanner := u.Other[0]
-				reposition.BringNodeToFront(u.BackgroundImgs[1].GetNode(), u)
-				reposition.BringNodeToFront(b.GetNode(), u)
-				for _, d := range u.DropTargets {
-					reposition.BringNodeToFront(d.GetCardHere().GetNode(), u)
-				}
-				if blueBanner.GetNode().Arranger == nil {
-					finalX := blueBanner.GetInitial().X
-					finalY := b.GetInitial().Y + b.GetDimensions().Y - blueBanner.GetDimensions().Y
-					finalPos := coords.MakeVec(finalX, finalY)
-					reposition.AnimateImageNoChannel(blueBanner, finalPos, blueBanner.GetDimensions(), u)
-				}
-			}
+		} else if b == u.Buttons["pass"] {
+			pressButton(b, u)
 		}
 	}
 }
 
 func moveClickPass(t touch.Event, u *uistate.UIState) {
-	if u.CurImg != nil {
-		imgs := make([]*staticimg.StaticImg, 0)
-		cards := make([]*card.Card, 0)
-		pullTab := u.Buttons["dragPass"]
-		blueBanner := u.BackgroundImgs[1]
-		imgs = append(imgs, pullTab)
-		imgs = append(imgs, blueBanner)
-		for _, d := range u.DropTargets {
-			imgs = append(imgs, d)
-			cards = append(cards, d.GetCardHere())
-		}
-		for i := 2; i < 7; i++ {
-			text := u.BackgroundImgs[i]
-			u.Eng.SetSubTex(text.GetNode(), text.GetAlt())
-			text.SetDisplayingImage(false)
-		}
-		reposition.DragImgs(t, cards, imgs, u)
-	} else if u.CurCard != nil {
+	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 endClickPass(t touch.Event, u *uistate.UIState) {
@@ -331,32 +288,50 @@
 				readyToPass = false
 			}
 		}
-		pullTab := u.Buttons["dragPass"]
+		passButton := u.Buttons["pass"]
 		if readyToPass {
-			u.Eng.SetSubTex(pullTab.GetNode(), pullTab.GetImage())
-			pullTab.SetDisplayingImage(true)
-		} else {
-			u.Eng.SetSubTex(pullTab.GetNode(), pullTab.GetAlt())
-			pullTab.SetDisplayingImage(false)
-		}
-	} else if u.CurImg != nil && touchingStaticImg(t, u.Other[0], u) {
-		ch := make(chan bool)
-		success := passCards(ch, u.CurPlayerIndex, u)
-		quit := make(chan bool)
-		u.AnimChans = append(u.AnimChans, quit)
-		go func() {
-			onDone := func() {
-				if !success {
-					fmt.Println("Invalid pass")
-				} else {
-					view.LoadTakeView(u)
+			if passButton.GetDisplayingImage() {
+				u.Eng.SetSubTex(passButton.GetNode(), passButton.GetImage())
+				passButton.SetDisplayingImage(true)
+			}
+			for _, img := range u.Other {
+				if img.GetDisplayingImage() {
+					u.Eng.SetSubTex(img.GetNode(), img.GetAlt())
+					img.SetDisplayingImage(false)
 				}
 			}
-			reposition.SwitchOnChan(ch, quit, onDone, u)
-		}()
+		} else {
+			var emptyTex sprite.SubTex
+			u.Eng.SetSubTex(passButton.GetNode(), emptyTex)
+			passButton.SetDisplayingImage(true)
+			for _, img := range u.Other {
+				if !img.GetDisplayingImage() {
+					u.Eng.SetSubTex(img.GetNode(), img.GetImage())
+					img.SetDisplayingImage(true)
+				}
+			}
+		}
+	}
+	pressed := unpressButtons(u)
+	for _, p := range pressed {
+		if p == u.Buttons["pass"] {
+			ch := make(chan bool)
+			success := passCards(ch, u.CurPlayerIndex, u)
+			quit := make(chan bool)
+			u.AnimChans = append(u.AnimChans, quit)
+			go func() {
+				onDone := func() {
+					if !success {
+						fmt.Println("Invalid pass")
+					} else {
+						view.LoadTakeView(u)
+					}
+				}
+				reposition.SwitchOnChan(ch, quit, onDone, u)
+			}()
+		}
 	}
 	u.CurCard = nil
-	u.CurImg = nil
 }
 
 func beginClickTake(t touch.Event, u *uistate.UIState) {
@@ -554,12 +529,10 @@
 // returns true if pass was successful
 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 {
 		passCard := d.GetCardHere()
 		if passCard != nil {
 			cardsPassed = append(cardsPassed, passCard)
-			dropsToReset = append(dropsToReset, d)
 		}
 	}
 	// if the pass is not valid, don't pass any cards
@@ -570,19 +543,9 @@
 	for !success {
 		success = sync.LogPass(u, cardsPassed)
 	}
-	// UI component
-	pullTab := u.Buttons["dragPass"]
-	blueBanner := u.BackgroundImgs[1]
-	imgs := []*staticimg.StaticImg{pullTab, blueBanner}
-	for _, d := range dropsToReset {
-		imgs = append(imgs, d)
-		d.SetCardHere(nil)
-	}
-	var blankTex sprite.SubTex
-	for _, i := range imgs {
-		u.Eng.SetSubTex(i.GetNode(), blankTex)
-	}
-	reposition.AnimateHandCardPass(ch, u.Other, cardsPassed, u)
+	imgs := append(u.Other, u.DropTargets...)
+	imgs = append(imgs, u.Buttons["pass"])
+	reposition.AnimateHandCardPass(ch, imgs, u)
 	return true
 }
 
@@ -622,7 +585,6 @@
 	if err := u.CurTable.ValidPlayLogic(c, playerId); err != "" {
 		return err
 	}
-	u.DropTargets[0].SetCardHere(nil)
 	success := sync.LogPlay(u, c)
 	for !success {
 		success = sync.LogPlay(u, c)
@@ -675,8 +637,8 @@
 			}
 			oldY := c.GetInitial().Y
 			suit := c.GetSuit()
-			u.CurCard.Move(d.GetCurrent(), c.GetDimensions(), u.Eng)
-			d.SetCardHere(u.CurCard)
+			c.Move(d.GetCurrent(), c.GetDimensions(), u.Eng)
+			d.SetCardHere(c)
 			// realign suit the card just left
 			reposition.RealignSuit(suit, oldY, u)
 			return true