Merge "Valid play logic, win condition, tests"
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..574583c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,9 @@
+# This is the official list of Vanadium authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as:
+#   Name or Organization <email address>
+# The email address is not required for organizations.
+
+# Please keep the list sorted.
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..b294e50
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,10 @@
+# People who have agreed to one of the CLAs and can contribute patches.
+# The AUTHORS file lists the copyright holders; this file
+# lists people.  For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+# https://developers.google.com/open-source/cla/individual
+# https://developers.google.com/open-source/cla/corporate
+#
+# Names should be added to this file as:
+#     Name <email address>
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..411db13
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2015 The Vanadium Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile b/Makefile
index 3fd20af..14f1cab 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,6 @@
 # very large, and can interfere with C++ memory if they are in the same
 # process.
 MOJO_SHELL_FLAGS := -v --enable-multiprocess \
-	--config-alias MOJO_BUILD_DIR=$(MOJO_BUILD_DIR) \
 	--config-alias SKY_DIR=$(SKY_DIR) \
 	--config-alias SKY_BUILD_DIR=$(SKY_BUILD_DIR) \
 	--config-alias ETHER_DIR=$(ETHER_DIR) \
@@ -52,12 +51,12 @@
 	dartfmt -w $(DART_LIB_FILES) $(DART_TEST_FILES)
 
 .PHONY: lint
-lint:
+lint: packages
 	dartanalyzer lib/main.dart | grep -v "\[warning\] The imported libraries"
 	dartanalyzer $(DART_TEST_FILES) | grep -v "\[warning\] The imported libraries"
 
 .PHONY: start
-start:
+start: packages
 	./packages/sky/sky_tool start --checked
 
 .PHONY: mock
@@ -92,7 +91,7 @@
 # If syncbase doesn't load, it could be that port 4002 is still in use; try fuser 4002/tcp.
 .PHONY: start-with-mojo
 start-with-mojo: env-check packages
-	$(MOJO_DIR)/src/mojo/devtools/common/mojo_run --config-file $(PWD)/mojoconfig $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) 'mojo:window_manager https://croupier.v.io/lib/main.dart'
+	$(MOJO_DIR)/src/mojo/devtools/common/mojo_run --config-file $(PWD)/mojoconfig $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) 'https://core.mojoapps.io/kiosk_wm.mojo https://croupier.v.io/lib/main.dart'
 
 # TODO(alexfandrianto): I split off the syncbase logic from game.dart because it
 # would not run in a stand-alone VM. We will need to add mojo_test eventually.
@@ -106,4 +105,4 @@
 
 .PHONY: clean
 clean:
-	rm -rf packages
+	rm -rf .packages packages .pubspec.lock
diff --git a/PATENTS b/PATENTS
new file mode 100644
index 0000000..d52cc55
--- /dev/null
+++ b/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Vanadium project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Vanadium, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Vanadium. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Vanadium or any code incorporated within this
+implementation of Vanadium constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Vanadium
+shall terminate as of the date such litigation is filed.
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..603150b
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+jiri-0.1
diff --git a/go/src/discovery/discovery.go b/go/src/discovery/discovery.go
index d15acd3..f703aa3 100644
--- a/go/src/discovery/discovery.go
+++ b/go/src/discovery/discovery.go
@@ -1,10 +1,14 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package discovery
 
 import (
-	"net/http"
-	"io/ioutil"
-	"strings"
 	"errors"
+	"io/ioutil"
+	"net/http"
+	"strings"
 )
 
 func FindNamespace(host string) (string, error) {
@@ -29,7 +33,7 @@
 						return cleanNamespace, nil
 					}
 				}
-			} 
+			}
 		}
 	}
 	//no instance of "v23.namespace.root=" is found
diff --git a/go/src/discovery/discovery_test.go b/go/src/discovery/discovery_test.go
index b311f88..f5798f0 100644
--- a/go/src/discovery/discovery_test.go
+++ b/go/src/discovery/discovery_test.go
@@ -1,5 +1,8 @@
-package discovery
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
 
+package discovery
 
 import (
 	"testing"
@@ -7,28 +10,28 @@
 
 //Testing a valid site with a valid namespace
 func TestOne(t *testing.T) {
-  	expect := "104.197.96.113:3389"
-  	host := "http://trustybike.net"
-  	ns, err := FindNamespace(host)
-  	if ns != expect {
+	expect := "104.197.96.113:3389"
+	host := "http://trustybike.net"
+	ns, err := FindNamespace(host)
+	if ns != expect {
 		t.Errorf("Expected \"%s\", got \"%s\" and error \"%s\"", expect, ns, err)
-  	}
+	}
 }
 
 //Testing an invalid site
 func TestTwo(t *testing.T) {
 	host := "not-a-website"
-  	ns, err := FindNamespace(host)
-  	if err == nil {
+	ns, err := FindNamespace(host)
+	if err == nil {
 		t.Errorf("Expected error, got \"%s\" and no error", ns)
-  	}
+	}
 }
 
 //Testing a valid site with no namespace
 func TestThree(t *testing.T) {
 	host := "http://www.facebook.com"
-  	ns, err := FindNamespace(host)
-  	if err == nil {
+	ns, err := FindNamespace(host)
+	if err == nil {
 		t.Errorf("Expected error, got \"%s\" and no error", ns)
-  	}
-}
\ No newline at end of file
+	}
+}
diff --git a/go/src/sprites/card/card.go b/go/src/sprites/card/card.go
index cbc2a25..4aefce0 100644
--- a/go/src/sprites/card/card.go
+++ b/go/src/sprites/card/card.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package card
 
 import (
diff --git a/go/src/sprites/display/main.go b/go/src/sprites/display/main.go
index 6a29388..6db900d 100644
--- a/go/src/sprites/display/main.go
+++ b/go/src/sprites/display/main.go
@@ -27,8 +27,6 @@
 // below. (Note: It currently doesn't work on Windows.)
 //   $ go install golang.org/x/mobile/example/sprite && sprite
 
-
-
 package main
 
 import (
@@ -37,8 +35,8 @@
 	//"math"
 	"time"
 
-	_ "image/jpeg"
 	_ "image/gif"
+	_ "image/jpeg"
 
 	"golang.org/x/mobile/app"
 	"golang.org/x/mobile/asset"
@@ -57,24 +55,24 @@
 )
 
 var (
-	startTime 			= time.Now()
-	eng       			= glsprite.Engine()
-	scene     			*sprite.Node
-	sprites   			[]*sprite.Node
-	spritesXY 			[][]float32
-	initialSpritesXY 	[][]float32
-	curSpriteIndex 		= -1
-	lastMouseXY	  		= []float32{-1,-1}
-	numCards   			= 4
-	numDropTargets 		= 3
-	numDecks			= 2
-	cardWidth 			= float32(175)
-	cardHeight 			= float32(245)
-	dropWidth 			= float32(768/2)
-	dropHeight 			= float32(620/2)
-	paddingSize 		= float32(cardWidth/5)
-	middleSize 			= float32(cardHeight)
-	windowSize 			= []float32{-1,-1}
+	startTime        = time.Now()
+	eng              = glsprite.Engine()
+	scene            *sprite.Node
+	sprites          []*sprite.Node
+	spritesXY        [][]float32
+	initialSpritesXY [][]float32
+	curSpriteIndex   = -1
+	lastMouseXY      = []float32{-1, -1}
+	numCards         = 4
+	numDropTargets   = 3
+	numDecks         = 2
+	cardWidth        = float32(175)
+	cardHeight       = float32(245)
+	dropWidth        = float32(768 / 2)
+	dropHeight       = float32(620 / 2)
+	paddingSize      = float32(cardWidth / 5)
+	middleSize       = float32(cardHeight)
+	windowSize       = []float32{-1, -1}
 )
 
 func main() {
@@ -100,62 +98,62 @@
 	switch t.Type.String() {
 	case "begin":
 		//i > numDropTargets excludes drop targets, draw, and discard so they can't move
-		for i := len(sprites)-1; i >= numDropTargets+2; i-- {
-			if t.X >= spritesXY[i][0] && 
-			   t.Y >= spritesXY[i][1] &&
-			   t.X <= spritesXY[i][2]+spritesXY[i][0] &&
-			   t.Y <= spritesXY[i][3]+spritesXY[i][1] {
-			   		curSpriteIndex = i
-			   		lastMouseXY[0] = t.X
-			   		lastMouseXY[1] = t.Y
-			   		return
-			   }
+		for i := len(sprites) - 1; i >= numDropTargets+2; i-- {
+			if t.X >= spritesXY[i][0] &&
+				t.Y >= spritesXY[i][1] &&
+				t.X <= spritesXY[i][2]+spritesXY[i][0] &&
+				t.Y <= spritesXY[i][3]+spritesXY[i][1] {
+				curSpriteIndex = i
+				lastMouseXY[0] = t.X
+				lastMouseXY[1] = t.Y
+				return
+			}
 		}
 		//checking if draw or discard is clicked
 		for i := 1; i >= 0; i-- {
-			if t.X >= spritesXY[i][0] && 
-			   t.Y >= spritesXY[i][1] &&
-			   t.X <= spritesXY[i][2]+spritesXY[i][0] &&
-			   t.Y <= spritesXY[i][3]+spritesXY[i][1] {
-			   		if i == 0 {
-			   			//draw is clicked
-			   			numCards++
+			if t.X >= spritesXY[i][0] &&
+				t.Y >= spritesXY[i][1] &&
+				t.X <= spritesXY[i][2]+spritesXY[i][0] &&
+				t.Y <= spritesXY[i][3]+spritesXY[i][1] {
+				if i == 0 {
+					//draw is clicked
+					numCards++
+					loadScene()
+				} else {
+					//discard is clicked
+					if numCards > 0 {
+						numCards--
 						loadScene()
-			   		} else {
-			   			//discard is clicked
-			   			if numCards > 0 {
-			   				numCards--
-			   				loadScene()
-			   			}
-			   		}
-			   }
+					}
+				}
+			}
 		}
 	case "move":
 		if curSpriteIndex > -1 {
 			eng.SetTransform(sprites[curSpriteIndex], f32.Affine{
-				{spritesXY[curSpriteIndex][2], 0, spritesXY[curSpriteIndex][0]+t.X-lastMouseXY[0]},
-				{0, spritesXY[curSpriteIndex][3], spritesXY[curSpriteIndex][1]+t.Y-lastMouseXY[1]},
+				{spritesXY[curSpriteIndex][2], 0, spritesXY[curSpriteIndex][0] + t.X - lastMouseXY[0]},
+				{0, spritesXY[curSpriteIndex][3], spritesXY[curSpriteIndex][1] + t.Y - lastMouseXY[1]},
 			})
-			spritesXY[curSpriteIndex][0] = spritesXY[curSpriteIndex][0]+t.X-lastMouseXY[0]
-			spritesXY[curSpriteIndex][1] = spritesXY[curSpriteIndex][1]+t.Y-lastMouseXY[1]
+			spritesXY[curSpriteIndex][0] = spritesXY[curSpriteIndex][0] + t.X - lastMouseXY[0]
+			spritesXY[curSpriteIndex][1] = spritesXY[curSpriteIndex][1] + t.Y - lastMouseXY[1]
 			lastMouseXY[0] = t.X
 			lastMouseXY[1] = t.Y
 		}
 	case "end":
 		onTarget := false
 		for i := 2; i < numDropTargets+2; i++ {
-			if curSpriteIndex > -1 && 
-			   spritesXY[curSpriteIndex][0] + spritesXY[curSpriteIndex][2]/2 >= spritesXY[i][0] && 
-			   spritesXY[curSpriteIndex][1] + spritesXY[curSpriteIndex][3]/2 >= spritesXY[i][1] && 
-			   spritesXY[curSpriteIndex][0] + spritesXY[curSpriteIndex][2]/2 <= spritesXY[i][2]+spritesXY[i][0] &&
-			   spritesXY[curSpriteIndex][1] + spritesXY[curSpriteIndex][3]/2 <= spritesXY[i][3]+spritesXY[i][1] {
-			   		eng.SetTransform(sprites[curSpriteIndex], f32.Affine{
-						{spritesXY[curSpriteIndex][2], 0, spritesXY[i][0]+spritesXY[i][2]/2-spritesXY[curSpriteIndex][2]/2},
-						{0, spritesXY[curSpriteIndex][3], spritesXY[i][1]+spritesXY[i][3]/2-spritesXY[curSpriteIndex][3]/2},
-					})
-					spritesXY[curSpriteIndex][0] = spritesXY[i][0]+spritesXY[i][2]/2-spritesXY[curSpriteIndex][2]/2
-					spritesXY[curSpriteIndex][1] = spritesXY[i][1]+spritesXY[i][3]/2-spritesXY[curSpriteIndex][3]/2
-					onTarget = true
+			if curSpriteIndex > -1 &&
+				spritesXY[curSpriteIndex][0]+spritesXY[curSpriteIndex][2]/2 >= spritesXY[i][0] &&
+				spritesXY[curSpriteIndex][1]+spritesXY[curSpriteIndex][3]/2 >= spritesXY[i][1] &&
+				spritesXY[curSpriteIndex][0]+spritesXY[curSpriteIndex][2]/2 <= spritesXY[i][2]+spritesXY[i][0] &&
+				spritesXY[curSpriteIndex][1]+spritesXY[curSpriteIndex][3]/2 <= spritesXY[i][3]+spritesXY[i][1] {
+				eng.SetTransform(sprites[curSpriteIndex], f32.Affine{
+					{spritesXY[curSpriteIndex][2], 0, spritesXY[i][0] + spritesXY[i][2]/2 - spritesXY[curSpriteIndex][2]/2},
+					{0, spritesXY[curSpriteIndex][3], spritesXY[i][1] + spritesXY[i][3]/2 - spritesXY[curSpriteIndex][3]/2},
+				})
+				spritesXY[curSpriteIndex][0] = spritesXY[i][0] + spritesXY[i][2]/2 - spritesXY[curSpriteIndex][2]/2
+				spritesXY[curSpriteIndex][1] = spritesXY[i][1] + spritesXY[i][3]/2 - spritesXY[curSpriteIndex][3]/2
+				onTarget = true
 			}
 		}
 		if onTarget == false && curSpriteIndex > -1 {
@@ -196,8 +194,8 @@
 		{0, ySize, y},
 	})
 	sprites = append(sprites, n)
-	spritesXY = append(spritesXY, []float32{x,y,xSize,ySize})
-	initialSpritesXY = append(initialSpritesXY, []float32{x,y,xSize,ySize})
+	spritesXY = append(spritesXY, []float32{x, y, xSize, ySize})
+	initialSpritesXY = append(initialSpritesXY, []float32{x, y, xSize, ySize})
 }
 
 func loadScene() {
@@ -212,27 +210,27 @@
 		{0, 1, 0},
 	})
 
-	dropXScaler := (float32(numDropTargets)*dropWidth+float32(numDropTargets+1)*paddingSize)/windowSize[0]
-	cardXScaler := (float32(numCards)*cardWidth+(float32(numCards)+1)*paddingSize)/windowSize[0]
-	deckXScaler := (float32(numDecks+2)*cardWidth+(float32(numDecks+2)+1)*paddingSize)/windowSize[0]
-	yScaler := (dropHeight+cardHeight+middleSize+4*paddingSize)/windowSize[1]
+	dropXScaler := (float32(numDropTargets)*dropWidth + float32(numDropTargets+1)*paddingSize) / windowSize[0]
+	cardXScaler := (float32(numCards)*cardWidth + (float32(numCards)+1)*paddingSize) / windowSize[0]
+	deckXScaler := (float32(numDecks+2)*cardWidth + (float32(numDecks+2)+1)*paddingSize) / windowSize[0]
+	yScaler := (dropHeight + cardHeight + middleSize + 4*paddingSize) / windowSize[1]
 	cardTexs := []sprite.SubTex{texs[card1], texs[card2], texs[card3], texs[card4]}
 	for yScaler > cardXScaler {
-		cardXScaler += (cardWidth+paddingSize)/windowSize[0]
+		cardXScaler += (cardWidth + paddingSize) / windowSize[0]
 	}
 	//deck and discard must be added first
-	addSprite((2*paddingSize+cardWidth)/deckXScaler, (2*paddingSize+cardHeight)/yScaler, 
+	addSprite((2*paddingSize+cardWidth)/deckXScaler, (2*paddingSize+cardHeight)/yScaler,
 		cardWidth/deckXScaler, cardHeight/yScaler, texs[draw])
-	addSprite((3*paddingSize+2*cardWidth)/deckXScaler, (2*paddingSize+cardHeight)/yScaler, 
+	addSprite((3*paddingSize+2*cardWidth)/deckXScaler, (2*paddingSize+cardHeight)/yScaler,
 		cardWidth/deckXScaler, cardHeight/yScaler, texs[discard])
 
 	//all drop targets must be added before all cards
 	for i := 0; i < numDropTargets; i++ {
-		addSprite((float32(i+1)*paddingSize+float32(i)*dropWidth)/dropXScaler, (cardHeight+middleSize+3*paddingSize)/yScaler, 
+		addSprite((float32(i+1)*paddingSize+float32(i)*dropWidth)/dropXScaler, (cardHeight+middleSize+3*paddingSize)/yScaler,
 			dropWidth/dropXScaler, dropHeight/yScaler, texs[dropTarget])
 	}
 	for i := 0; i < numCards; i++ {
-		addSprite((float32(i+1)*paddingSize+float32(i)*cardWidth)/cardXScaler, paddingSize/yScaler, 
+		addSprite((float32(i+1)*paddingSize+float32(i)*cardWidth)/cardXScaler, paddingSize/yScaler,
 			cardWidth/cardXScaler, cardHeight/cardXScaler, cardTexs[i%len(cardTexs)])
 	}
 }
@@ -294,13 +292,12 @@
 	}
 
 	return []sprite.SubTex{
-		card1: sprite.SubTex{t, image.Rect(15, 15, 190, 260)},
-		card2: sprite.SubTex{t, image.Rect(195, 60, 370, 305)},
-		card3: sprite.SubTex{t, image.Rect(375, 107, 550, 350)},
-		card4: sprite.SubTex{t, image.Rect(555, 135, 730, 377)},
-		dropTarget: sprite.SubTex{t2, image.Rect(0,0,766,620)},
-		draw: sprite.SubTex{t3, image.Rect(0,0,1506/2,1052)},
-		discard: sprite.SubTex{t3, image.Rect(1506/2,0,1506,1052)},
+		card1:      sprite.SubTex{t, image.Rect(15, 15, 190, 260)},
+		card2:      sprite.SubTex{t, image.Rect(195, 60, 370, 305)},
+		card3:      sprite.SubTex{t, image.Rect(375, 107, 550, 350)},
+		card4:      sprite.SubTex{t, image.Rect(555, 135, 730, 377)},
+		dropTarget: sprite.SubTex{t2, image.Rect(0, 0, 766, 620)},
+		draw:       sprite.SubTex{t3, image.Rect(0, 0, 1506/2, 1052)},
+		discard:    sprite.SubTex{t3, image.Rect(1506/2, 0, 1506, 1052)},
 	}
 }
-
diff --git a/go/src/sprites/logic.go b/go/src/sprites/logic.go
index 871b866..2450e59 100644
--- a/go/src/sprites/logic.go
+++ b/go/src/sprites/logic.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package main
 
 import (
diff --git a/go/src/sprites/logic_test.go b/go/src/sprites/logic_test.go
index 68934a4..22f2465 100644
--- a/go/src/sprites/logic_test.go
+++ b/go/src/sprites/logic_test.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package main
 
 import (
diff --git a/go/src/sprites/player/player.go b/go/src/sprites/player/player.go
index 9fc30db..dee1739 100644
--- a/go/src/sprites/player/player.go
+++ b/go/src/sprites/player/player.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package player
 
 import (
diff --git a/go/src/sprites/table/table.go b/go/src/sprites/table/table.go
index 508b89b..8816922 100644
--- a/go/src/sprites/table/table.go
+++ b/go/src/sprites/table/table.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package table
 
 import (
diff --git a/go/src/sprites/ui/assets/Clubs-10.png b/go/src/sprites/ui/assets/Clubs-10.png
new file mode 100644
index 0000000..4a4f778
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-10.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-2.png b/go/src/sprites/ui/assets/Clubs-2.png
new file mode 100644
index 0000000..ae28aea
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-2.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-3.png b/go/src/sprites/ui/assets/Clubs-3.png
new file mode 100644
index 0000000..9630282
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-3.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-4.png b/go/src/sprites/ui/assets/Clubs-4.png
new file mode 100644
index 0000000..0542f8a
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-4.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-5.png b/go/src/sprites/ui/assets/Clubs-5.png
new file mode 100644
index 0000000..fe2a818
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-5.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-6.png b/go/src/sprites/ui/assets/Clubs-6.png
new file mode 100644
index 0000000..466930b
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-6.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-7.png b/go/src/sprites/ui/assets/Clubs-7.png
new file mode 100644
index 0000000..a75bdbb
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-7.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-8.png b/go/src/sprites/ui/assets/Clubs-8.png
new file mode 100644
index 0000000..22f0100
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-8.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-9.png b/go/src/sprites/ui/assets/Clubs-9.png
new file mode 100644
index 0000000..61299cc
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-9.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-Ace.png b/go/src/sprites/ui/assets/Clubs-Ace.png
new file mode 100644
index 0000000..2a0b778
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-Ace.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-Jack.png b/go/src/sprites/ui/assets/Clubs-Jack.png
new file mode 100644
index 0000000..f12514f
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-Jack.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-King.png b/go/src/sprites/ui/assets/Clubs-King.png
new file mode 100644
index 0000000..783321f
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-King.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Clubs-Queen.png b/go/src/sprites/ui/assets/Clubs-Queen.png
new file mode 100644
index 0000000..addf04d
--- /dev/null
+++ b/go/src/sprites/ui/assets/Clubs-Queen.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-10.png b/go/src/sprites/ui/assets/Diamonds-10.png
new file mode 100644
index 0000000..5afdbea
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-10.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-2.png b/go/src/sprites/ui/assets/Diamonds-2.png
new file mode 100644
index 0000000..51b5534
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-2.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-3.png b/go/src/sprites/ui/assets/Diamonds-3.png
new file mode 100644
index 0000000..ebb082f
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-3.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-4.png b/go/src/sprites/ui/assets/Diamonds-4.png
new file mode 100644
index 0000000..1240a9f
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-4.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-5.png b/go/src/sprites/ui/assets/Diamonds-5.png
new file mode 100644
index 0000000..df381ec
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-5.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-6.png b/go/src/sprites/ui/assets/Diamonds-6.png
new file mode 100644
index 0000000..43e4347
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-6.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-7.png b/go/src/sprites/ui/assets/Diamonds-7.png
new file mode 100644
index 0000000..ed87b34
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-7.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-8.png b/go/src/sprites/ui/assets/Diamonds-8.png
new file mode 100644
index 0000000..eef9ee7
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-8.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-9.png b/go/src/sprites/ui/assets/Diamonds-9.png
new file mode 100644
index 0000000..6410b5e
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-9.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-Ace.png b/go/src/sprites/ui/assets/Diamonds-Ace.png
new file mode 100644
index 0000000..d605a72
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-Ace.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-Jack.png b/go/src/sprites/ui/assets/Diamonds-Jack.png
new file mode 100644
index 0000000..43e40cf
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-Jack.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-King.png b/go/src/sprites/ui/assets/Diamonds-King.png
new file mode 100644
index 0000000..66da79d
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-King.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Diamonds-Queen.png b/go/src/sprites/ui/assets/Diamonds-Queen.png
new file mode 100644
index 0000000..d5cd590
--- /dev/null
+++ b/go/src/sprites/ui/assets/Diamonds-Queen.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-10.png b/go/src/sprites/ui/assets/Hearts-10.png
new file mode 100644
index 0000000..eb67655
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-10.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-2.png b/go/src/sprites/ui/assets/Hearts-2.png
new file mode 100644
index 0000000..d9d1782
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-2.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-3.png b/go/src/sprites/ui/assets/Hearts-3.png
new file mode 100644
index 0000000..83f5ff6
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-3.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-4.png b/go/src/sprites/ui/assets/Hearts-4.png
new file mode 100644
index 0000000..89c7ff7
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-4.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-5.png b/go/src/sprites/ui/assets/Hearts-5.png
new file mode 100644
index 0000000..5a9f089
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-5.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-6.png b/go/src/sprites/ui/assets/Hearts-6.png
new file mode 100644
index 0000000..f3e32e4
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-6.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-7.png b/go/src/sprites/ui/assets/Hearts-7.png
new file mode 100644
index 0000000..b2d291d
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-7.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-8.png b/go/src/sprites/ui/assets/Hearts-8.png
new file mode 100644
index 0000000..4366a45
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-8.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-9.png b/go/src/sprites/ui/assets/Hearts-9.png
new file mode 100644
index 0000000..9bf626f
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-9.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-Ace.png b/go/src/sprites/ui/assets/Hearts-Ace.png
new file mode 100644
index 0000000..b5fda7d
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-Ace.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-Jack.png b/go/src/sprites/ui/assets/Hearts-Jack.png
new file mode 100644
index 0000000..1f74ff7
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-Jack.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-King.png b/go/src/sprites/ui/assets/Hearts-King.png
new file mode 100644
index 0000000..166d13b
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-King.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Hearts-Queen.png b/go/src/sprites/ui/assets/Hearts-Queen.png
new file mode 100644
index 0000000..c7b55af
--- /dev/null
+++ b/go/src/sprites/ui/assets/Hearts-Queen.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-10.png b/go/src/sprites/ui/assets/Spades-10.png
new file mode 100644
index 0000000..ab3ef54
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-10.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-2.png b/go/src/sprites/ui/assets/Spades-2.png
new file mode 100644
index 0000000..4b2df7c
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-2.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-3.png b/go/src/sprites/ui/assets/Spades-3.png
new file mode 100644
index 0000000..f950455
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-3.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-4.png b/go/src/sprites/ui/assets/Spades-4.png
new file mode 100644
index 0000000..e0e9a39
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-4.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-5.png b/go/src/sprites/ui/assets/Spades-5.png
new file mode 100644
index 0000000..9dffd38
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-5.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-6.png b/go/src/sprites/ui/assets/Spades-6.png
new file mode 100644
index 0000000..edded91
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-6.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-7.png b/go/src/sprites/ui/assets/Spades-7.png
new file mode 100644
index 0000000..3c95f28
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-7.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-8.png b/go/src/sprites/ui/assets/Spades-8.png
new file mode 100644
index 0000000..2c26e47
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-8.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-9.png b/go/src/sprites/ui/assets/Spades-9.png
new file mode 100644
index 0000000..51874ac
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-9.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-Ace.png b/go/src/sprites/ui/assets/Spades-Ace.png
new file mode 100644
index 0000000..e7d7bb5
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-Ace.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-Jack.png b/go/src/sprites/ui/assets/Spades-Jack.png
new file mode 100644
index 0000000..8e625c5
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-Jack.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-King.png b/go/src/sprites/ui/assets/Spades-King.png
new file mode 100644
index 0000000..c706bce
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-King.png
Binary files differ
diff --git a/go/src/sprites/ui/assets/Spades-Queen.png b/go/src/sprites/ui/assets/Spades-Queen.png
new file mode 100644
index 0000000..84de08d
--- /dev/null
+++ b/go/src/sprites/ui/assets/Spades-Queen.png
Binary files differ
diff --git a/go/src/sprites/ui/ui.go b/go/src/sprites/ui/ui.go
new file mode 100644
index 0000000..dc1a8ab
--- /dev/null
+++ b/go/src/sprites/ui/ui.go
@@ -0,0 +1,253 @@
+package main
+
+import (
+	"image"
+	"log"
+	"math"
+	"time"
+
+	_ "image/png"
+
+	"golang.org/x/mobile/app"
+	"golang.org/x/mobile/asset"
+	"golang.org/x/mobile/event/paint"
+	"golang.org/x/mobile/event/size"
+	"golang.org/x/mobile/event/touch"
+	"golang.org/x/mobile/exp/f32"
+	"golang.org/x/mobile/exp/sprite"
+	"golang.org/x/mobile/exp/sprite/clock"
+	"golang.org/x/mobile/exp/sprite/glsprite"
+	"golang.org/x/mobile/gl"
+)
+
+var (
+	startTime          = time.Now()
+	eng                = glsprite.Engine()
+	scene              *sprite.Node
+	cards              []*sprite.Node
+	cardsXY            [][]float32
+	initialCardsXY     [][]float32
+	curCardIndex       = -1
+	lastMouseXY        = []float32{-1, -1}
+	cardWidth          = float32(100)
+	cardHeight         = float32(100)
+	windowSize         = []float32{-1, -1}
+	swipeMoveThreshold = 70
+	swipeTimeThreshold = .5
+	swipeStart         time.Time
+	animSpeedScaler    = .1
+	animRotationScaler = .15
+)
+
+func main() {
+	app.Main(func(a app.App) {
+		var sz size.Event
+		for e := range a.Events() {
+			switch e := app.Filter(e).(type) {
+			case size.Event:
+				sz = e
+				windowSize[0] = float32(sz.WidthPx)
+				windowSize[1] = float32(sz.HeightPx)
+			case touch.Event:
+				onTouch(e)
+			case paint.Event:
+				onPaint(sz)
+				a.EndPaint(e)
+			}
+		}
+	})
+}
+
+func onTouch(t touch.Event) {
+	switch t.Type.String() {
+	case "begin":
+		for i := len(cards) - 1; i >= 0; i-- {
+			if t.X >= getCardX(i) &&
+				t.Y >= getCardY(i) &&
+				t.X <= cardWidth+getCardX(i) &&
+				t.Y <= cardHeight+getCardY(i) {
+				swipeStart = time.Now()
+				curCardIndex = i
+				node := getCardNode(i)
+				node.Arranger = nil
+				lastMouseXY[0] = t.X
+				lastMouseXY[1] = t.Y
+				return
+			}
+		}
+	case "move":
+		if curCardIndex > -1 {
+			eng.SetTransform(cards[curCardIndex], f32.Affine{
+				{cardWidth, 0, getCardX(curCardIndex) + t.X - lastMouseXY[0]},
+				{0, cardHeight, getCardY(curCardIndex) + t.Y - lastMouseXY[1]},
+			})
+			setCardX(curCardIndex, getCardX(curCardIndex)+t.X-lastMouseXY[0])
+			setCardY(curCardIndex, getCardY(curCardIndex)+t.Y-lastMouseXY[1])
+			lastMouseXY[0] = t.X
+			lastMouseXY[1] = t.Y
+		}
+	case "end":
+		if curCardIndex > -1 {
+			xDiff := getCardX(curCardIndex) - getInitialX(curCardIndex)
+			yDiff := getCardY(curCardIndex) - getInitialY(curCardIndex)
+			timeDiff := time.Since(swipeStart).Seconds()
+			if (math.Abs(float64(xDiff))+math.Abs(float64(yDiff))) >= float64(swipeMoveThreshold) && timeDiff <= float64(swipeTimeThreshold) {
+				animate(xDiff, yDiff, t)
+			} else {
+				eng.SetTransform(cards[curCardIndex], f32.Affine{
+					{cardWidth, 0, getInitialX(curCardIndex)},
+					{0, cardHeight, getInitialY(curCardIndex)},
+				})
+				setCardX(curCardIndex, getInitialX(curCardIndex))
+				setCardY(curCardIndex, getInitialY(curCardIndex))
+			}
+		}
+		curCardIndex = -1
+	}
+}
+
+func animate(xDiff float32, yDiff float32, touch touch.Event) {
+	index := curCardIndex
+	curCardIndex = -1
+	node := getCardNode(index)
+	startTime := -1
+	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
+		if startTime == -1 {
+			startTime = int(t)
+		}
+		moveSpeed := float32(int(t)-startTime) * float32(animSpeedScaler)
+		x := getCardX(index)
+		y := getCardY(index)
+		if math.Abs(float64(xDiff)) > math.Abs(float64(yDiff)) {
+			if xDiff > 0 {
+				x = x + moveSpeed
+			} else {
+				x = x - moveSpeed
+			}
+		} else {
+			if yDiff > 0 {
+				y = y + moveSpeed
+			} else {
+				y = y - moveSpeed
+			}
+		}
+		setCardX(index, x)
+		setCardY(index, y)
+		position := f32.Affine{
+			{cardWidth, 0, x + cardWidth/2},
+			{0, cardHeight, y + cardHeight/2},
+		}
+		position.Rotate(&position, float32(t)*float32(animRotationScaler))
+		position.Translate(&position, -.5, -.5)
+		eng.SetTransform(node, position)
+	})
+}
+
+func onPaint(sz size.Event) {
+	if scene == nil {
+		loadScene()
+	}
+	gl.ClearColor(1, 1, 1, 1)
+	gl.Clear(gl.COLOR_BUFFER_BIT)
+	now := clock.Time(time.Since(startTime) * 60 / time.Second)
+	eng.Render(scene, now, sz)
+}
+
+func newNode() *sprite.Node {
+	n := &sprite.Node{}
+	eng.Register(n)
+	scene.AppendChild(n)
+	return n
+}
+
+func addCard(x float32, y float32, spriteTex sprite.SubTex) {
+	n := newNode()
+	eng.SetSubTex(n, spriteTex)
+	eng.SetTransform(n, f32.Affine{
+		{cardWidth, 0, x},
+		{0, cardHeight, y},
+	})
+	cards = append(cards, n)
+	cardsXY = append(cardsXY, []float32{x, y})
+	initialCardsXY = append(initialCardsXY, []float32{x, y})
+}
+
+func getCardX(cardIndex int) float32 {
+	return cardsXY[cardIndex][0]
+}
+
+func setCardX(cardIndex int, newX float32) {
+	cardsXY[cardIndex][0] = newX
+}
+
+func getCardY(cardIndex int) float32 {
+	return cardsXY[cardIndex][1]
+}
+
+func setCardY(cardIndex int, newY float32) {
+	cardsXY[cardIndex][1] = newY
+}
+
+func getCardNode(cardIndex int) *sprite.Node {
+	return cards[cardIndex]
+}
+
+func getInitialX(cardIndex int) float32 {
+	return initialCardsXY[cardIndex][0]
+}
+
+func getInitialY(cardIndex int) float32 {
+	return initialCardsXY[cardIndex][1]
+}
+
+func loadScene() {
+	cards = make([]*sprite.Node, 0)
+	cardsXY = make([][]float32, 0)
+	initialCardsXY = make([][]float32, 0)
+	texs := loadTextures()
+	scene = &sprite.Node{}
+	eng.Register(scene)
+	eng.SetTransform(scene, f32.Affine{
+		{1, 0, 0},
+		{0, 1, 0},
+	})
+	for _, v := range texs {
+		x := windowSize[0]/2 - cardWidth/2
+		y := windowSize[1]/2 - cardHeight/2
+		addCard(x, y, v)
+	}
+}
+
+func loadTextures() map[string]sprite.SubTex {
+	allTexs := make(map[string]sprite.SubTex)
+	files := []string{"Clubs-2.png", "Clubs-3.png", "Clubs-4.png", "Clubs-5.png", "Clubs-6.png", "Clubs-7.png", "Clubs-8.png",
+		"Clubs-9.png", "Clubs-10.png", "Clubs-Jack.png", "Clubs-Queen.png", "Clubs-King.png", "Clubs-Ace.png",
+		"Diamonds-2.png", "Diamonds-3.png", "Diamonds-4.png", "Diamonds-5.png", "Diamonds-6.png", "Diamonds-7.png", "Diamonds-8.png",
+		"Diamonds-9.png", "Diamonds-10.png", "Diamonds-Jack.png", "Diamonds-Queen.png", "Diamonds-King.png", "Diamonds-Ace.png",
+		"Spades-2.png", "Spades-3.png", "Spades-4.png", "Spades-5.png", "Spades-6.png", "Spades-7.png", "Spades-8.png",
+		"Spades-9.png", "Spades-10.png", "Spades-Jack.png", "Spades-Queen.png", "Spades-King.png", "Spades-Ace.png",
+		"Hearts-2.png", "Hearts-3.png", "Hearts-4.png", "Hearts-5.png", "Hearts-6.png", "Hearts-7.png", "Hearts-8.png",
+		"Hearts-9.png", "Hearts-10.png", "Hearts-Jack.png", "Hearts-Queen.png", "Hearts-King.png", "Hearts-Ace.png"}
+	for _, f := range files {
+		a, err := asset.Open(f)
+		if err != nil {
+			log.Fatal(err)
+		}
+		defer a.Close()
+
+		img, _, err := image.Decode(a)
+		if err != nil {
+			log.Fatal(err)
+		}
+		t, err := eng.LoadTexture(img)
+		if err != nil {
+			log.Fatal(err)
+		}
+		allTexs[f] = sprite.SubTex{t, image.Rect(0, 0, 100, 100)}
+	}
+	return allTexs
+}
+
+type arrangerFunc func(e sprite.Engine, n *sprite.Node, t clock.Time)
+
+func (a arrangerFunc) Arrange(e sprite.Engine, n *sprite.Node, t clock.Time) { a(e, n, t) }
diff --git a/lib/components/board.dart b/lib/components/board.dart
index 9b3772f..e1c4636 100644
--- a/lib/components/board.dart
+++ b/lib/components/board.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import './card.dart' show Card;
 import '../logic/card.dart' as logic_card;
 
diff --git a/lib/components/card.dart b/lib/components/card.dart
index 37dc4d4..9844c02 100644
--- a/lib/components/card.dart
+++ b/lib/components/card.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import '../logic/card.dart' as logic_card;
 import 'package:sky/widgets.dart' as widgets;
 
diff --git a/lib/components/card_collection.dart b/lib/components/card_collection.dart
index 5484373..6456bb9 100644
--- a/lib/components/card_collection.dart
+++ b/lib/components/card_collection.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import '../logic/card.dart' as logic_card;
 import 'card.dart' as component_card;
 import 'draggable.dart' show Draggable;
diff --git a/lib/components/croupier.dart b/lib/components/croupier.dart
index e5cedc3..d1a448a 100644
--- a/lib/components/croupier.dart
+++ b/lib/components/croupier.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import '../logic/croupier.dart' as logic_croupier;
 import '../logic/game.dart' as logic_game;
 import 'game.dart' show createGameComponent;
diff --git a/lib/components/draggable.dart b/lib/components/draggable.dart
index 6d23330..973b895 100644
--- a/lib/components/draggable.dart
+++ b/lib/components/draggable.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import 'dart:sky' as sky;
 
 import 'package:sky/widgets.dart' as widgets;
diff --git a/lib/components/game.dart b/lib/components/game.dart
index 3753a75..cb634d4 100644
--- a/lib/components/game.dart
+++ b/lib/components/game.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import '../logic/card.dart' as logic_card;
 import '../logic/game.dart'
     show Game, GameType, Viewer, HeartsGame, HeartsPhase;
diff --git a/lib/logic/card.dart b/lib/logic/card.dart
index 195bc1e..1303daf 100644
--- a/lib/logic/card.dart
+++ b/lib/logic/card.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import 'dart:collection';
 
 class Card {
diff --git a/lib/logic/croupier.dart b/lib/logic/croupier.dart
index 494e29e..bfc573d 100644
--- a/lib/logic/croupier.dart
+++ b/lib/logic/croupier.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import 'game.dart' show Game, GameType;
 
 enum CroupierState {
diff --git a/lib/logic/game.dart b/lib/logic/game.dart
index 94c0224..08ddaa8 100644
--- a/lib/logic/game.dart
+++ b/lib/logic/game.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import 'card.dart' show Card;
 import 'dart:math' as math;
 import 'syncbase_echo.dart' show SyncbaseEcho;
diff --git a/lib/logic/syncbase_echo.dart b/lib/logic/syncbase_echo.dart
index cacfd2f..ece3781 100644
--- a/lib/logic/syncbase_echo.dart
+++ b/lib/logic/syncbase_echo.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import 'game.dart' show Game, GameType, GameLog, GameCommand;
 
 class SyncbaseEcho extends Game {
diff --git a/lib/main.dart b/lib/main.dart
index ae59599..9067267 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import 'package:sky/widgets.dart';
 
 import 'logic/croupier.dart' show Croupier;
diff --git a/lib/src/mocks/log_writer.dart b/lib/src/mocks/log_writer.dart
index 7f3a1d5..c1b5fce 100644
--- a/lib/src/mocks/log_writer.dart
+++ b/lib/src/mocks/log_writer.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 class LogWriter {
   final Function updateCallback; // Takes in Map<String, String> data
   LogWriter(this.updateCallback);
diff --git a/lib/src/syncbase/log_writer.dart b/lib/src/syncbase/log_writer.dart
index c7386fa..3c11406 100644
--- a/lib/src/syncbase/log_writer.dart
+++ b/lib/src/syncbase/log_writer.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 /// The goal of log writer is to generically manage game logs.
 /// Syncbase will produce values that combine to form a List<GameCommand> while
 /// the in-memory GameLog will also hold such a list.
diff --git a/lib/src/syncbase/syncbase_echo_impl.dart b/lib/src/syncbase/syncbase_echo_impl.dart
index 2eedd71..d8569ec 100644
--- a/lib/src/syncbase/syncbase_echo_impl.dart
+++ b/lib/src/syncbase/syncbase_echo_impl.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import 'dart:async';
 import 'dart:convert' show UTF8;
 
diff --git a/test/hearts_test.dart b/test/hearts_test.dart
index e907855..3aa1da7 100644
--- a/test/hearts_test.dart
+++ b/test/hearts_test.dart
@@ -1,3 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 import "package:test/test.dart";
 import "../lib/logic/game.dart";
 import "../lib/logic/card.dart";