This adds a few starting pages for the Hearts app.
- Welcome Screen
- Game Chooser
- We skip Arrange Players entirely, but can add that later.
- Then we can play "Hearts". Or "Proto" as I'm calling it now.

I also split apart Game into subclasses for ease of use.
ProtoGame and HeartsGame are subclasses that override its "move" method.
diff --git a/lib/components/croupier.dart b/lib/components/croupier.dart
new file mode 100644
index 0000000..38909a8
--- /dev/null
+++ b/lib/components/croupier.dart
@@ -0,0 +1,78 @@
+import '../logic/croupier.dart' as logic_croupier;
+import '../logic/game.dart' as logic_game;
+import 'package:sky/widgets.dart' show FlatButton;
+import 'package:sky/widgets/basic.dart';
+import 'game.dart' show GameComponent;
+import 'dart:sky' as sky;
+
+class CroupierComponent extends StatefulComponent {
+  logic_croupier.Croupier croupier;
+
+  CroupierComponent(this.croupier) : super();
+
+  void syncFields(CroupierComponent other) {
+    croupier = other.croupier;
+  }
+
+  Function setStateCallbackFactory(logic_croupier.CroupierState s, [var data = null]) {
+    return () => setState(() {
+      croupier.setState(s, data);
+    });
+  }
+
+  Widget build() {
+    switch (croupier.state) {
+      case logic_croupier.CroupierState.Welcome:
+        // in which we show them a UI to start a new game, join a game, or change some settings.
+        return new Container(
+          padding: new EdgeDims.only(top: sky.view.paddingTop),
+          child: new Flex([
+            new FlatButton(
+              child: new Text('Create Game'),
+              onPressed: setStateCallbackFactory(logic_croupier.CroupierState.ChooseGame)
+            ),
+            new FlatButton(
+              child: new Text('Join Game')
+            ),
+            new FlatButton(
+              child: new Text('Settings')
+            )
+          ], direction: FlexDirection.vertical
+        )
+      );
+      case logic_croupier.CroupierState.Settings:
+        return null; // in which we let them pick an avatar, name, and color. And return to the previous screen after (NOT IMPLEMENTED YET)
+      case logic_croupier.CroupierState.ChooseGame:
+        // in which we let them pick a game out of the many possible games... There aren't that many.
+        return new Container(
+          padding: new EdgeDims.only(top: sky.view.paddingTop),
+          child: new Flex([
+            new FlatButton(
+              child: new Text('Proto'),
+              onPressed: setStateCallbackFactory(logic_croupier.CroupierState.PlayGame, logic_game.GameType.Proto)
+            ),
+            new FlatButton(
+              child: new Text('Hearts'),
+              onPressed: setStateCallbackFactory(logic_croupier.CroupierState.PlayGame, logic_game.GameType.Hearts)
+            ),
+            new FlatButton(
+              child: new Text('Poker')
+            ),
+            new FlatButton(
+              child: new Text('Solitaire')
+            )
+          ], direction: FlexDirection.vertical
+        )
+      );
+      case logic_croupier.CroupierState.AwaitGame:
+        return null; // in which players wait for game invitations to arrive.
+      case logic_croupier.CroupierState.ArrangePlayers:
+        return null; // If needed, lists the players around and what devices they'd like to use.
+      case logic_croupier.CroupierState.PlayGame:
+        return new GameComponent(croupier.game); // Asks the game UI to draw itself.
+      default:
+        assert(false);
+        return null;
+    }
+  }
+}
\ No newline at end of file
diff --git a/lib/components/game.dart b/lib/components/game.dart
index defc49b..ab5eea5 100644
--- a/lib/components/game.dart
+++ b/lib/components/game.dart
@@ -23,10 +23,13 @@
 
   Widget build() {
     switch (game.gameType) {
+      case GameType.Proto:
+        return buildProto();
       case GameType.Hearts:
         return buildHearts();
-        // Code to display board:
-        //return new Board(1, [2,3,4], [1, 2, 3, 4]); Does NOT work in checked mode since it has a Stack of Positioned Stack with Positioned Widgets.
+      case GameType.Board:
+        // Does NOT work in checked mode since it has a Stack of Positioned Stack with Positioned Widgets.
+        return new Board(1, [2,3,4], [1, 2, 3, 4]);
       default:
         return null; // unsupported
     }
@@ -44,7 +47,7 @@
     });
   }
 
-  Widget buildHearts() {
+  Widget buildProto() {
     List<Widget> cardCollections = new List<Widget>();
 
     // debugString
@@ -100,4 +103,31 @@
       child: new Flex(cardCollections, direction: FlexDirection.vertical)//new Stack(cardCollections)
     );
   }
+
+  Widget buildHearts() {
+    List<Widget> cardCollections = new List<Widget>();
+
+    cardCollections.add(new Text(game.debugString));
+
+    for (int i = 0; i < 4; i++) {
+      List<Card> cards = game.cardCollections[i];
+      CardCollectionComponent c = new CardCollectionComponent(cards, game.playerNumber == i, Orientation.horz, _updateGameCallback);
+      cardCollections.add(c); // flex
+    }
+
+    cardCollections.add(new Container(
+      decoration: new BoxDecoration(backgroundColor: colors.Green[500], borderRadius: 5.0),
+      child: new CardCollectionComponent(game.cardCollections[4], true, Orientation.show1, _updateGameCallback)
+    ));
+
+    cardCollections.add(new FlatButton(
+      child: new Text('Switch View'),
+      onPressed: _switchPlayersCallback
+    ));
+
+    return new Container(
+      decoration: new BoxDecoration(backgroundColor: colors.Pink[500]),
+      child: new Flex(cardCollections, direction: FlexDirection.vertical)
+    );
+  }
 }
diff --git a/lib/logic/croupier.dart b/lib/logic/croupier.dart
new file mode 100644
index 0000000..9a548cc
--- /dev/null
+++ b/lib/logic/croupier.dart
@@ -0,0 +1,65 @@
+import 'game.dart' show Game, GameType;
+
+enum CroupierState {
+  Welcome, Settings, ChooseGame, AwaitGame, ArrangePlayers, PlayGame
+}
+
+class Croupier {
+  CroupierState state;
+  Settings settings;
+  Game game; // null until chosen
+
+  Croupier() {
+    state = CroupierState.Welcome;
+    // settings = new Settings.load(?); // Give it in the croupier constructor. The app itself should load this info.
+  }
+
+  // Sets the next part of croupier state.
+  // Depending on the originating state, data can contain extra information that we need.
+  void setState(CroupierState nextState, var data) {
+    switch (state) {
+      case CroupierState.Welcome:
+        // data should be empty.
+        assert(data == null);
+        break;
+      case CroupierState.Settings:
+        // data should be empty.
+        // All settings changes affect the croupier settings directly without changing app state.
+        assert(data == null);
+        break;
+      case CroupierState.ChooseGame:
+        // data should be the game id here.
+        GameType gt = data as GameType;
+        game = new Game(gt, 0); // Start as player 0 of whatever game type.
+        break;
+      case CroupierState.AwaitGame:
+        // data would probably be the game id again.
+        GameType gt = data as GameType;
+        game = new Game(gt, 0); // Start as player 0 of whatever game type.
+        break;
+      case CroupierState.ArrangePlayers:
+        // data should be empty.
+        // All rearrangements affect the Game's player number without changing app state.
+        break;
+      case CroupierState.PlayGame:
+        // data should be empty.
+        // The signal to start really isn't anything special.
+        break;
+      default:
+        assert(false);
+    }
+
+    state = nextState;
+  }
+}
+
+class Settings {
+  String avatar;
+  String name;
+  String color; // in hex?
+
+  Settings(this.avatar, this.name, this.color);
+
+  // Settings.load(String data) {}
+  // String save() { return null; }
+}
\ No newline at end of file
diff --git a/lib/logic/game.dart b/lib/logic/game.dart
index 08c1285..df02af9 100644
--- a/lib/logic/game.dart
+++ b/lib/logic/game.dart
@@ -1,8 +1,11 @@
 import 'card.dart' show Card;
 import 'dart:math' show Random;
 
+// Note: Proto and Board are "fake" games intended to demonstrate what we can do.
+// Proto is just a drag cards around "game".
+// Board is meant to show how one _could_ layout a game of Hearts. This one is not hooked up very well yet.
 enum GameType {
-  Hearts
+  Proto, Hearts, Poker, Solitaire, Board
 }
 
 /// A game consists of multiple decks and tracks a single deck of cards.
@@ -15,27 +18,28 @@
   final Random random = new Random();
   final GameLog gamelog = new GameLog();
   int playerNumber;
-  Function updateCallback;
   String debugString = 'hello?';
 
-  Game.hearts(this.playerNumber) : gameType = GameType.Hearts {
+  Function updateCallback; // Used to inform components of when a change has occurred. This is especially important when something non-UI related changes what should be drawn.
+
+  factory Game(GameType gt, int pn) {
+    switch (gt) {
+      case GameType.Proto:
+        return new ProtoGame(pn);
+      case GameType.Hearts:
+        return new HeartsGame(pn);
+      default:
+        assert(false);
+        return null;
+    }
+  }
+
+  // A super constructor, don't call this unless you're a subclass.
+  Game._create(this.gameType, this.playerNumber, int numCollections) {
     gamelog.setGame(this);
-
-    // playerNumber would be used in a real game, but I have to ignore it for debugging.
-    // It would determine faceUp/faceDown status.
-
-    deck.shuffle();
-    cardCollections.add(new List<Card>()); // Player A
-    cardCollections.add(new List<Card>()); // Player B
-    cardCollections.add(new List<Card>()); // Player C
-    cardCollections.add(new List<Card>()); // Player D
-    cardCollections.add(new List<Card>()); // an empty pile
-    cardCollections.add(new List<Card>()); // a hidden pile!
-
-    /*deal(0, 8);
-    deal(1, 5);
-    deal(2, 4);
-    deal(3, 1);*/
+    for (int i = 0; i < numCollections; i++) {
+      cardCollections.add(new List<Card>());
+    }
   }
 
   List<Card> deckPeek(int numCards) {
@@ -44,10 +48,42 @@
     return cards;
   }
 
+  // Which card collection has the card?
+  int findCard(Card card) {
+    for (int i = 0; i < cardCollections.length; i++) {
+      if (cardCollections[i].contains(card)) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  // UNIMPLEMENTED: Let subclasses override this?
+  // Or is it improper to do so?
+  void move(Card card, List<Card> dest) {}
+}
+
+class ProtoGame extends Game {
+  ProtoGame(int playerNumber) : super._create(GameType.Proto, playerNumber, 6) {
+    // playerNumber would be used in a real game, but I have to ignore it for debugging.
+    // It would determine faceUp/faceDown status.faceDown
+
+    // TODO: Set the number of piles created to either 9 (1x per player, 1 discard, 4 play piles) or 12 (2x per player, 4 play piles)
+    // But for now, we will deal with 6. 1x per player, 1 discard, and 1 undrawn pile.
+
+    // We do some arbitrary things here... Just for setup.
+    deck.shuffle();
+    deal(0, 8);
+    deal(1, 5);
+    deal(2, 4);
+    deal(3, 1);
+  }
+
   void deal(int playerId, int numCards) {
     gamelog.add(new HeartsCommand.deal(playerId, this.deckPeek(numCards)));
   }
 
+  // Overrides Game's move method with the "move" logic for the card dragging prototype.
   void move(Card card, List<Card> dest) {
     // The first step is to find the card. Where is it?
     // then we can remove it and add to the dest.
@@ -61,23 +97,51 @@
 
     gamelog.add(new HeartsCommand.pass(i, destId, <Card>[card]));
 
-    /*cardCollections[i].remove(card);
-    dest.add(card);*/
     debugString = 'Move ${i} ${card.toString()}';
     print(debugString);
   }
+}
 
-  // Which card collection has the card?
-  int findCard(Card card) {
-    for (int i = 0; i < cardCollections.length; i++) {
-      if (cardCollections[i].contains(card)) {
-        return i;
-      }
+class HeartsGame extends Game {
+  HeartsGame(int playerNumber) : super._create(GameType.Hearts, playerNumber, 6) {
+    // playerNumber would be used in a real game, but I have to ignore it for debugging.
+    // It would determine faceUp/faceDown status.faceDown
+
+    // TODO: Set the number of piles created to either 9 (1x per player, 1 discard, 4 play piles) or 12 (2x per player, 4 play piles)
+    // But for now, we will deal with 6. 1x per player, 1 discard, and 1 undrawn pile.
+
+    // We do some arbitrary things here... Just for setup.
+    deck.shuffle();
+    deal(0, 8);
+    deal(1, 5);
+    deal(2, 4);
+    deal(3, 1);
+  }
+
+  void deal(int playerId, int numCards) {
+    gamelog.add(new HeartsCommand.deal(playerId, this.deckPeek(numCards)));
+  }
+
+  // Overrides Game's move method with the "move" logic for Hearts.
+  void move(Card card, List<Card> dest) {
+    // The first step is to find the card. Where is it?
+    // then we can remove it and add to the dest.
+    debugString = 'Moving... ${card.toString()}';
+    int i = findCard(card);
+    if (i == -1) {
+      debugString = 'NO... ${card.toString()}';
+      return;
     }
-    return -1;
+    int destId = cardCollections.indexOf(dest);
+
+    gamelog.add(new HeartsCommand.pass(i, destId, <Card>[card]));
+
+    debugString = 'Move ${i} ${card.toString()}';
+    print(debugString);
   }
 }
 
+
 class GameLog {
   Game game;
   List<GameCommand> log = new List<GameCommand>();
diff --git a/lib/main.dart b/lib/main.dart
index 7a6ea14..ef523a3 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -7,22 +7,24 @@
 //import 'package:sky/theme/colors.dart' as colors;
 import 'package:sky/widgets.dart';
 
-import 'logic/game.dart' show Game, HeartsCommand;
-import 'components/game.dart' show GameComponent;
+//import 'logic/game.dart' show Game, HeartsCommand;
+//import 'components/game.dart' show GameComponent;
+import 'logic/croupier.dart' show Croupier;
+import 'components/croupier.dart' show CroupierComponent;
 
-import 'dart:io';
-import 'dart:convert';
-import 'dart:async';
+//import 'dart:io';
+//import 'dart:convert';
+//import 'dart:async';
 
 class CroupierApp extends App {
-  Game game;
+  Croupier croupier;
 
   CroupierApp() : super() {
-    this.game = new Game.hearts(0);
+    this.croupier = new Croupier();
   }
 
   Widget build() {
-    return new GameComponent(this.game);
+    return new CroupierComponent(this.croupier);
   }
 }
 
@@ -31,7 +33,7 @@
 
   // Had difficulty reading from a file, so I can use this to simulate it.
   // Seems like only NetworkImage exists, but why not also have NetworkFile?
-  List<String> commands = <String>[
+  /*List<String> commands = <String>[
     "Deal:0:classic h1:classic h2:classic h3:classic h4:END",
     "Deal:1:classic d1:classic d2:classic d3:classic d4:END",
     "Deal:2:classic s1:classic s2:classic s3:classic s4:END",
@@ -49,10 +51,8 @@
         app.game.gamelog.add(new HeartsCommand(commands[i]));
       });
     }
-  });
+  });*/
 
 
   runApp(app);
-
-
 }
\ No newline at end of file