public FleetRender( Fleet fleet, bool? lines )
        {
            LineGeometry line;
            FormattedText text;
            Geometry textGeom;

            double x = fleet.SourcePlanet.X +
                       ((fleet.DestinationPlanet.X - fleet.SourcePlanet.X) *
                        ((double)(fleet.TotalTripLength - fleet.TurnsRemaining) / fleet.TotalTripLength));
            double y = fleet.SourcePlanet.Y +
                       ((fleet.DestinationPlanet.Y - fleet.SourcePlanet.Y) *
                        ((double)(fleet.TotalTripLength - fleet.TurnsRemaining) / fleet.TotalTripLength));

            if (lines ?? false)
            {
                line = new LineGeometry(new Point(x, y), new Point(fleet.DestinationPlanet.X, fleet.DestinationPlanet.Y));
                m_gg.Children.Add(line);
            }

            text = new FormattedText(
                fleet.ShipCount.ToString(),
                CultureInfo.CurrentCulture,
                FlowDirection.LeftToRight,
                new Typeface("Tahoma"),
                0.8,
                Brushes.Black);
            textGeom = text.BuildGeometry(new Point(x - text.Width / 2, y - text.Height / 2));
            m_gg.Children.Add(textGeom);

            m_gg.Freeze();
        }
        private void ParseGameState(string s)
        {
            m_Planets.Clear();
            m_Fleets.Clear();
            int planetID = 0;

            string[] lines = s.Split('\n');
            for (int i = 0; i < lines.Length; ++i)
            {
                string line         = lines[i];
                int    commentBegin = line.IndexOf('#');
                if (commentBegin >= 0)
                {
                    line = line.Substring(0, commentBegin);
                }
                if (line.Trim().Length == 0)
                {
                    continue;
                }

                string[] tokens = line.Split(' ');
                if (tokens.Length == 0)
                {
                    continue;
                }

                switch (tokens[0])
                {
                case "P":
                {
                    /* P <x:float> <y:float> <owner:int> <ships:int> <growth:int> */
                    if (tokens.Length != 6)
                    {
                        throw new Exception("Invalid planet clause");
                    }
                    double x          = double.Parse(tokens[1]);
                    double y          = double.Parse(tokens[2]);
                    int    ownerId    = int.Parse(tokens[3]);
                    int    numShips   = int.Parse(tokens[4]);
                    int    growthRate = int.Parse(tokens[5]);
                    Planet p          = new Planet(
                        planetID++,
                        Players.Singleton[ownerId],
                        numShips,
                        growthRate,
                        x, y,
                        this
                        );
                    m_Planets.Add(p);
                    break;
                }

                case "F":
                {
                    /* F <owner:int> <ships:int> <source:int> <destination:int> <total_turns:int> <remaining_turns:int> */
                    if (tokens.Length != 7)
                    {
                        throw new Exception("Invalid fleet clause");
                    }
                    int   ownerId         = int.Parse(tokens[1]);
                    int   numShips        = int.Parse(tokens[2]);
                    int   source          = int.Parse(tokens[3]);
                    int   destination     = int.Parse(tokens[4]);
                    int   totalTripLength = int.Parse(tokens[5]);
                    int   turnsRemaining  = int.Parse(tokens[6]);
                    Fleet f = new Fleet(
                        Players.Singleton[ownerId],
                        numShips,
                        m_Planets[source],
                        m_Planets[destination],
                        totalTripLength,
                        turnsRemaining,
                        this
                        );
                    m_Fleets.Add(f);
                    break;
                }

                default:
                    throw new Exception(String.Format("Unrecognised clause {0}", tokens[0]));
                }
            }
        }