Incorporating take trick functionality

Change-Id: I393c6b93138087531c6fcb14af94c8761506815c
diff --git a/go/src/hearts/assets/TakePressed.png b/go/src/hearts/assets/TakePressed.png
new file mode 100644
index 0000000..527dfee
--- /dev/null
+++ b/go/src/hearts/assets/TakePressed.png
Binary files differ
diff --git a/go/src/hearts/assets/TakeTrickHandPressed.png b/go/src/hearts/assets/TakeTrickHandPressed.png
index b6fc11e..ef3cbc9 100644
--- a/go/src/hearts/assets/TakeTrickHandPressed.png
+++ 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
index ae111ad..e78def1 100644
--- a/go/src/hearts/assets/TakeTrickHandUnpressed.png
+++ b/go/src/hearts/assets/TakeTrickHandUnpressed.png
Binary files differ
diff --git a/go/src/hearts/assets/TakeUnpressed.png b/go/src/hearts/assets/TakeUnpressed.png
new file mode 100644
index 0000000..75d54c8
--- /dev/null
+++ b/go/src/hearts/assets/TakeUnpressed.png
Binary files differ
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index 1d83c72..6d30a40 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -204,6 +204,9 @@
 // Animation to bring in the take slot
 func AnimateInTake(u *uistate.UIState) {
 	imgs := append(u.Other, u.DropTargets...)
+	if u.Buttons["take"] != nil {
+		imgs = append(imgs, u.Buttons["take"])
+	}
 	for _, i := range imgs {
 		dims := i.GetDimensions()
 		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y)
@@ -281,9 +284,9 @@
 	tableImgs := make([]*staticimg.StaticImg, 0)
 	bannerImgs := make([]*staticimg.StaticImg, 0)
 	bannerImgs = append(bannerImgs, u.Other...)
+	bannerImgs = append(bannerImgs, u.Buttons["takeTrick"])
 	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()
@@ -320,9 +323,9 @@
 	tableImgs := make([]*staticimg.StaticImg, 0)
 	bannerImgs := make([]*staticimg.StaticImg, 0)
 	bannerImgs = append(bannerImgs, u.Other...)
+	bannerImgs = append(bannerImgs, u.Buttons["takeTrick"])
 	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()
@@ -388,9 +391,21 @@
 	}
 }
 
-func AnimateHandCardTakeTrick(ch chan bool, c *card.Card, u *uistate.UIState) {
-	destination := c.GetDimensions().Times(-1)
-	animateCardMovement(ch, c, destination, c.GetDimensions(), u)
+func AnimateHandCardTakeTrick(ch chan bool, cards []*card.Card, u *uistate.UIState) {
+	imgs := append(u.DropTargets, u.BackgroundImgs[0])
+	for _, i := range imgs {
+		dims := i.GetDimensions()
+		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y-u.WindowSize.Y/3-u.TopPadding)
+		AnimateImageNoChannel(i, to, dims, u)
+	}
+	for i, c := range cards {
+		destination := c.GetDimensions().Times(-1)
+		if i < len(cards) - 1 {
+			animateCardNoChannel(c, destination, c.GetDimensions(), u)
+		} else {
+			animateCardMovement(ch, c, destination, c.GetDimensions(), u)
+		}
+	}
 }
 
 func animateImageMovement(c chan bool, animImage *staticimg.StaticImg, endPos, endDim *coords.Vec, u *uistate.UIState) {
diff --git a/go/src/hearts/img/texture/texture.go b/go/src/hearts/img/texture/texture.go
index 2ffc183..f59d539 100644
--- a/go/src/hearts/img/texture/texture.go
+++ b/go/src/hearts/img/texture/texture.go
@@ -277,7 +277,7 @@
 		"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", "TakeTrickTableUnpressed.png", "TakeTrickTablePressed.png", "TakeTrickHandPressed.png",
-		"TakeTrickHandUnpressed.png", "android.png", "cat.png", "man.png", "woman.png",
+		"TakeTrickHandUnpressed.png", "android.png", "cat.png", "man.png", "woman.png", "TakeUnpressed.png", "TakePressed.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 6b8a78f..d88f3da 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -47,7 +47,7 @@
 // Arrange view: For seating players
 func LoadArrangeView(u *uistate.UIState) {
 	u.M.Lock()
-	fmt.Println("ARRANGE LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -88,15 +88,13 @@
 			u.Eng.SetSubTex(u.Buttons["start"].GetNode(), emptyTex)
 		}
 	}
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 // 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) {
 	u.M.Lock()
-	fmt.Println("WAITING LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -107,14 +105,12 @@
 	for _, img := range textImgs {
 		u.BackgroundImgs = append(u.BackgroundImgs, img)
 	}
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 // Discovery view: Displays a menu of possible games to join
 func LoadDiscoveryView(u *uistate.UIState) {
 	u.M.Lock()
-	fmt.Println("DISCOVERY LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -155,14 +151,12 @@
 			}
 		}
 	}
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 // Table View: Displays the table. Intended for public devices
 func LoadTableView(u *uistate.UIState) {
 	u.M.Lock()
-	fmt.Println("TABLE LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -378,8 +372,6 @@
 		addDebugBar(u)
 	}
 	reposition.SetTableDropColors(u)
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 // Decides which view of the player's hand to load based on what steps of the round they have completed
@@ -397,7 +389,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) {
 	u.M.Lock()
-	fmt.Println("SCORE LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -406,14 +398,12 @@
 	addScoreViewHeaderText(u)
 	addPlayerScores(roundScores, u)
 	addScoreButton(len(winners) > 0, u)
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 // Pass View: Shows player's hand and allows them to pass cards
 func LoadPassView(u *uistate.UIState) {
 	u.M.Lock()
-	fmt.Println("PASS LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -426,14 +416,12 @@
 		addDebugBar(u)
 	}
 	reposition.AnimateInPass(u)
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 // 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.M.Lock()
-	fmt.Println("TAKE LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -447,14 +435,12 @@
 	}
 	// animate in take bar
 	reposition.AnimateInTake(u)
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 // Play View: Shows player's hand and allows them to play cards
 func LoadPlayView(u *uistate.UIState) {
 	u.M.Lock()
-	fmt.Println("PLAY LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -478,13 +464,11 @@
 	} else if u.CurTable.GetTrickRecipient() == u.CurPlayerIndex {
 		reposition.AnimateInPlay(u)
 	}
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 func LoadSplitView(reloading bool, u *uistate.UIState) {
 	u.M.Lock()
-	fmt.Println("SPLIT LOCKED")
+	defer u.M.Unlock()
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -508,8 +492,6 @@
 			reposition.SwitchOnChan(ch, quit, onDone, u)
 		}()
 	}
-	u.M.Unlock()
-	fmt.Println("UNLOCKED")
 }
 
 func ChangePlayMessage(message string, u *uistate.UIState) {
@@ -676,9 +658,9 @@
 		if u.CurTable.TrickOver() {
 			recipient := u.CurTable.GetTrickRecipient()
 			if recipient == u.CurPlayerIndex {
-				turnText = "Please take your trick"
+				turnText = ""
 			} else {
-				turnText = fmt.Sprintf("Waiting for %s to take the trick", uistate.GetName(recipient, u))
+				turnText = fmt.Sprintf("%s's trick", uistate.GetName(recipient, u))
 			}
 		} else {
 			turnText = "Waiting for other players"
@@ -731,8 +713,13 @@
 		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)
+	takeTrickDim := coords.MakeVec(3*u.CardDim.X/2, 3*u.CardDim.Y/4)
+	takeTrickPos := headerDimensions.MinusVec(takeTrickDim).DividedBy(2)
+	if u.CurView == uistate.Play || beforeSplitAnimation {
+		takeTrickPos = coords.MakeVec(takeTrickPos.X, takeTrickPos.Y+u.TopPadding/2+headerPos.Y)
+	} else {
+		takeTrickPos = coords.MakeVec(takeTrickPos.X, takeTrickPos.Y+u.TopPadding/2+headerPos.Y-5)
+	}
 	display := (u.CurTable.TrickOver() && u.CurTable.GetTrickRecipient() == u.CurPlayerIndex)
 	u.Buttons["takeTrick"] = texture.MakeImgWithAlt(takeTrickImage, takeTrickAlt, takeTrickPos, takeTrickDim, true, u)
 	if !display {
@@ -816,16 +803,16 @@
 	numDrops := 3
 	dropXStart := (u.WindowSize.X - (float32(numDrops)*u.CardDim.X + (float32(numDrops)-1)*u.Padding)) / 2
 	dropImg := u.Texs["trickDrop.png"]
+	passDim := coords.MakeVec(3*u.CardDim.X/2, 2*u.CardDim.Y/3)
 	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)
+		dropPos := coords.MakeVec(dropX, topOfHand-2*u.Padding-u.WindowSize.Y-20-passDim.Y)
 		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)
+	passPos := coords.MakeVec((u.WindowSize.X-passDim.X)/2, topOfHand-2*u.Padding-u.WindowSize.Y-20-passDim.Y+u.CardDim.Y+u.Padding)
 	b := texture.MakeImgWithAlt(passImg, passAlt, passPos, passDim, true, u)
 	var emptyTex sprite.SubTex
 	u.Eng.SetSubTex(b.GetNode(), emptyTex)
@@ -868,15 +855,19 @@
 	color := "Gray"
 	nameAltColor := "LBlue"
 	awaitingAltColor := "None"
-	center := coords.MakeVec(u.WindowSize.X/2, 20-u.WindowSize.Y)
+	center := coords.MakeVec(u.WindowSize.X/2, 50-u.WindowSize.Y)
+	if !display {
+		center = coords.MakeVec(center.X, center.Y-30)
+		name = "Take from " + name
+	}
 	scaler := float32(3)
 	maxWidth := grayBarDim.X - 2*u.Padding
 	u.Other = append(u.Other,
 		texture.MakeStringImgCenterAlign(name, color, nameAltColor, display, center, scaler, maxWidth, u)...)
-	center = coords.MakeVec(center.X, center.Y+30)
+	center = coords.MakeVec(center.X, center.Y-30)
 	scaler = float32(5)
 	u.Other = append(u.Other,
-		texture.MakeStringImgCenterAlign("Awaiting pass", color, awaitingAltColor, display, center, scaler, maxWidth, u)...)
+		texture.MakeStringImgCenterAlign("Awaiting pass from", color, awaitingAltColor, display, center, scaler, maxWidth, u)...)
 	// adding cards to take, if cards have been passed
 	if !display {
 		u.Cards = append(u.Cards, passedCards...)
@@ -884,6 +875,7 @@
 }
 
 func moveTakeCards(u *uistate.UIState) {
+	topOfHand := u.WindowSize.Y - 5*(u.CardDim.Y+u.Padding) - (2 * u.Padding / 5) - u.BottomPadding
 	passedCards := make([]*card.Card, 0)
 	if u.SequentialPhases {
 		if u.CurTable.AllDonePassing() {
@@ -893,12 +885,18 @@
 		passedCards = append(passedCards, u.CurTable.GetPlayers()[u.CurPlayerIndex].GetPassedTo()...)
 	}
 	if len(passedCards) > 0 {
+		takeImg := u.Texs["TakeUnpressed.png"]
+		takeAlt := u.Texs["TakePressed.png"]
+		takeDim := coords.MakeVec(3*u.CardDim.X/2, 2*u.CardDim.Y/3)
+		takePos := coords.MakeVec((u.WindowSize.X-takeDim.X)/2, topOfHand-2*u.Padding-u.WindowSize.Y-20-takeDim.Y+u.CardDim.Y+u.Padding)
+		b := texture.MakeImgWithAlt(takeImg, takeAlt, takePos, takeDim, true, u)
+		u.Buttons["take"] = b
 		topOfHand := u.WindowSize.Y - 5*(u.CardDim.Y+u.Padding) - (2 * u.Padding / 5) - u.BottomPadding
 		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, topOfHand-u.Padding-u.WindowSize.Y-20)
+			cardPos := coords.MakeVec(cardX, topOfHand-2*u.Padding-u.WindowSize.Y-20-takeDim.Y)
 			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/sync/watch.go b/go/src/hearts/sync/watch.go
index 3def64c..f2f2195 100644
--- a/go/src/hearts/sync/watch.go
+++ b/go/src/hearts/sync/watch.go
@@ -21,6 +21,8 @@
 	"sort"
 	"strconv"
 	"strings"
+	"os"
+	"time"
 	"v.io/v23/syncbase/nosql"
 )
 
@@ -97,6 +99,12 @@
 	if err != nil {
 		fmt.Println("WatchData error:", err)
 	}
+	file, err2 := os.OpenFile("/sdcard/test.txt", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
+	if err2 != nil {
+		fmt.Println("err2:", err2)
+	}
+	fmt.Fprintf(file, fmt.Sprintf("\n***NEW GAME: %d\n", u.GameID))
+	defer file.Close()
 	updateBlock := make([]nosql.WatchChange, 0)
 	for {
 		if updateExists := stream.Advance(); updateExists {
@@ -104,22 +112,33 @@
 			updateBlock = append(updateBlock, c)
 			if !c.Continued {
 				sort.Sort(updateSorter(updateBlock))
-				handleGameUpdate(updateBlock, u)
+				handleGameUpdate(file, updateBlock, u)
 				updateBlock = make([]nosql.WatchChange, 0)
 			}
 		}
 	}
 }
 
-func handleGameUpdate(changes []nosql.WatchChange, u *uistate.UIState) {
+func handleGameUpdate(file *os.File, changes []nosql.WatchChange, u *uistate.UIState) {
 	for _, c := range changes {
 		if c.ChangeType == nosql.PutChange {
 			key := c.Row
+			curTime := time.Now().UnixNano() / 1000000
 			var value []byte
 			if err := c.Value(&value); err != nil {
 				fmt.Println("Value error:", err)
 			}
 			valueStr := string(value)
+			fmt.Fprintf(file, fmt.Sprintf("key: %s\n", key))
+			fmt.Fprintf(file, fmt.Sprintf("value: %s\n", valueStr))
+			fmt.Fprintf(file, fmt.Sprintf("time: %v\n", curTime))
+			tmp := strings.Split(key, "/")
+			if len(tmp) == 3 {
+				keyTime, _ := strconv.ParseInt(strings.Split(tmp[2], "-")[0], 10, 64)
+				fmt.Fprintf(file, fmt.Sprintf("diff: %d milliseconds\n\n", curTime - keyTime))
+			} else {
+				fmt.Fprintf(file, "\n")
+			}
 			fmt.Println(key, valueStr)
 			keyType := strings.Split(key, "/")[1]
 			switch keyType {
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index eee5b3c..bafcec1 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -95,27 +95,18 @@
 		case touch.TypeBegin:
 			beginClickTake(t, u)
 		case touch.TypeMove:
-			if u.CurCard != nil {
-				moveClickTake(t, u)
-			}
+			moveClickTake(t, u)
 		case touch.TypeEnd:
-			if u.CurCard != nil {
-				endClickTake(t, u.CurCard, u)
-				u.CurCard = nil
-			}
+			endClickTake(t, u)
 		}
 	case uistate.Play:
 		switch t.Type {
 		case touch.TypeBegin:
 			beginClickPlay(t, u)
 		case touch.TypeMove:
-			if u.CurCard != nil {
-				moveClickPlay(t, u)
-			}
+			moveClickPlay(t, u)
 		case touch.TypeEnd:
-			if u.CurCard != nil {
-				endClickPlay(t, u.CurCard, u)
-			}
+			endClickPlay(t, u)
 		}
 	case uistate.Split:
 		switch t.Type {
@@ -379,54 +370,60 @@
 }
 
 func beginClickTake(t touch.Event, u *uistate.UIState) {
-	u.CurCard = findClickedCard(t, u)
-	if u.CurCard != nil {
-		reposition.BringNodeToFront(u.CurCard.GetNode(), u)
-		u.CurCard.GetNode().Arranger = nil
-	}
 	buttonList := findClickedButton(t, u)
 	for _, b := range buttonList {
 		if b == u.Buttons["table"] {
 			view.LoadTableView(u)
 		} else if b == u.Buttons["hand"] {
 			view.LoadPassOrTakeOrPlay(u)
+		} else if b == u.Buttons["take"] {
+			pressButton(b, u)
 		}
 	}
 }
 
 func moveClickTake(t touch.Event, u *uistate.UIState) {
-	reposition.DragCard(t, u)
+	curPressed := findClickedButton(t, u)
+	alreadyPressed := getPressed(u)
+	if len(alreadyPressed) > 0 && len(curPressed) == 0 {
+		unpressButtons(u)
+	}
 }
 
-func endClickTake(t touch.Event, c *card.Card, u *uistate.UIState) {
-	// check to see if card was removed from a drop target
-	removeCardFromTarget(c, u)
-	// add card back to hand
-	reposition.ResetCardPosition(c, u.Eng)
-	reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
-	doneTaking := len(u.DropTargets) == 3
-	for _, d := range u.DropTargets {
-		if d.GetCardHere() != nil {
-			doneTaking = false
-		}
-	}
-	if doneTaking {
-		ch := make(chan bool)
-		success := takeCards(ch, u.CurPlayerIndex, u)
-		quit := make(chan bool)
-		u.AnimChans = append(u.AnimChans, quit)
-		go func() {
-			onDone := func() {
-				if !success {
-					fmt.Println("Invalid take")
-				} else {
-					if u.CurView == uistate.Take {
-						view.LoadPlayView(u)
-					}
+func endClickTake(t touch.Event, u *uistate.UIState) {
+	pressed := unpressButtons(u)
+	for _, b := range pressed {
+		if b == u.Buttons["take"] {
+			cards := make([]*card.Card, 0)
+			for _, d := range u.DropTargets {
+				c := d.GetCardHere()
+				if c != nil {
+					cards = append(cards, c)
 				}
 			}
-			reposition.SwitchOnChan(ch, quit, onDone, u)
-		}()
+			for _, c := range cards {
+				removeCardFromTarget(c, u)
+				// add card back to hand
+				reposition.ResetCardPosition(c, u.Eng)
+				reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
+			}
+			ch := make(chan bool)
+			success := takeCards(ch, u.CurPlayerIndex, u)
+			quit := make(chan bool)
+			u.AnimChans = append(u.AnimChans, quit)
+			go func() {
+				onDone := func() {
+					if !success {
+						fmt.Println("Invalid take")
+					} else {
+						if u.CurView == uistate.Take {
+							view.LoadPlayView(u)
+						}
+					}
+				}
+				reposition.SwitchOnChan(ch, quit, onDone, u)
+			}()
+		}
 	}
 }
 
@@ -435,29 +432,6 @@
 	if u.CurCard != nil {
 		reposition.BringNodeToFront(u.CurCard.GetNode(), u)
 	}
-	takenCard := findClickedTableCard(t, u)
-	if takenCard != nil {
-		removeCardFromTarget(takenCard, u)
-		reposition.BringNodeToFront(takenCard.GetNode(), u)
-		ch := make(chan bool)
-		reposition.AnimateHandCardTakeTrick(ch, takenCard, u)
-		quit := make(chan bool)
-		u.AnimChans = append(u.AnimChans, quit)
-		go func() {
-			onDone := func() {
-				doneTaking := len(u.DropTargets) == 4
-				for _, d := range u.DropTargets {
-					if d.GetCardHere() != nil {
-						doneTaking = false
-					}
-				}
-				if doneTaking {
-					sync.LogTakeTrick(u)
-				}
-			}
-			reposition.SwitchOnChan(ch, quit, onDone, u)
-		}()
-	}
 	buttonList := findClickedButton(t, u)
 	for _, b := range buttonList {
 		if b == u.Buttons["toggleSplit"] && !u.SwitchingViews {
@@ -466,40 +440,73 @@
 			view.LoadTableView(u)
 		} else if b == u.Buttons["hand"] {
 			view.LoadPassOrTakeOrPlay(u)
+		} else if b == u.Buttons["takeTrick"] {
+			pressButton(b, u)
 		}
 	}
 }
 
 func moveClickPlay(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 endClickPlay(t touch.Event, c *card.Card, u *uistate.UIState) {
-	if dropCardOnTarget(c, t, u) {
-		ch := make(chan bool)
-		if err := playCard(ch, u.CurPlayerIndex, u); err != "" {
-			view.ChangePlayMessage(err, u)
-			removeCardFromTarget(c, u)
-			// add card back to hand
-			reposition.ResetCardPosition(c, u.Eng)
-			reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
-		}
-		quit := make(chan bool)
-		u.AnimChans = append(u.AnimChans, quit)
-		go func() {
-			onDone := func() {
-				if u.CurView == uistate.Play {
-					view.LoadPlayView(u)
-				}
+func endClickPlay(t touch.Event, u *uistate.UIState) {
+	if u.CurCard != nil {
+		if dropCardOnTarget(u.CurCard, 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)
+				reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
 			}
-			reposition.SwitchOnChan(ch, quit, onDone, u)
-		}()
-	} else {
-		// check to see if card was removed from a drop target
-		removeCardFromTarget(c, u)
-		// add card back to hand
-		reposition.ResetCardPosition(c, u.Eng)
-		reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
+			quit := make(chan bool)
+			u.AnimChans = append(u.AnimChans, quit)
+			go func() {
+				onDone := func() {
+					if u.CurView == uistate.Play {
+						view.LoadPlayView(u)
+					}
+				}
+				reposition.SwitchOnChan(ch, quit, onDone, u)
+			}()
+		} else {
+			// check to see if card was removed from a drop target
+			removeCardFromTarget(u.CurCard, u)
+			// add card back to hand
+			reposition.ResetCardPosition(u.CurCard, u.Eng)
+			reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
+		}
+	}
+	pressed := unpressButtons(u)
+	for _, b := range pressed {
+		if b == u.Buttons["takeTrick"] {
+			var emptyTex sprite.SubTex
+			u.Eng.SetSubTex(b.GetNode(), emptyTex)
+			u.Buttons["takeTrick"] = nil
+			for _, takenCard := range u.TableCards {
+				removeCardFromTarget(takenCard, u)
+				reposition.BringNodeToFront(takenCard.GetNode(), u)
+			}
+			ch := make(chan bool)
+			reposition.AnimateHandCardTakeTrick(ch, u.TableCards, u)
+			quit := make(chan bool)
+			u.AnimChans = append(u.AnimChans, quit)
+			go func() {
+				onDone := func() {
+					sync.LogTakeTrick(u)
+				}
+				reposition.SwitchOnChan(ch, quit, onDone, u)
+			}()
+		}
 	}
 }
 
@@ -623,8 +630,10 @@
 func findClickedButton(t touch.Event, u *uistate.UIState) []*staticimg.StaticImg {
 	pressed := make([]*staticimg.StaticImg, 0)
 	for _, b := range u.Buttons {
-		if touchingStaticImg(t, b, u) {
-			pressed = append(pressed, b)
+		if b != nil {
+			if touchingStaticImg(t, b, u) {
+				pressed = append(pressed, b)
+			}
 		}
 	}
 	return pressed
@@ -663,7 +672,8 @@
 	for !success {
 		success = sync.LogTake(u)
 	}
-	reposition.AnimateHandCardTake(ch, u.Other, u)
+	imgs := append(u.Other, u.Buttons["take"])
+	reposition.AnimateHandCardTake(ch, imgs, u)
 	return true
 }