public static string Parse(string line, IGameplayEngine bot)
        {
            string result = null;

            if (line == null)
            {
                // null indicates exit
                return null;
            }

            line = line.Trim();

            if (line.Length == 0)
            {
                return "";
            }

            String[] parts = InputParser.Split(line);

            if (parts[0].Equals("pick_starting_regions"))
            {
                result = PickStartingRegions(bot, parts);
            }
            else if (parts.Length == 3 && parts[0].Equals("go"))
            {
                result = Go(bot, parts);
            }
            else if (parts.Length == 3 && parts[0].Equals("settings"))
            {
                ProcessSettings(bot, parts);
            }
            else if (parts[0].Equals("setup_map"))
            {
                bot.State.SetupMap(parts);
            }
            else if (parts[0].Equals("update_map"))
            {
                //all visible regions are given
                bot.State.UpdateMap(parts);
            }
            else if (parts[0].Equals("opponent_moves"))
            {
                //all visible opponent moves are given
                bot.ProcessOpponentMoves(MoveParser.ParseMoves(bot.State.FullMap, line));
            }
            else
            {
                Console.Error.WriteLine("Unable to parse line '{0}'", line);
            }

            return result;
        }
        protected virtual void ProcessPlayerMoves(IGameplayEngine actingPlayer, IGameplayEngine opponent, List<Move> moves)
        {
            if (!moves.Any())
            {
                ConsoleExtensions.WriteColoredLine(ConsoleColor.Red, "Player '{0}' made no moves!", actingPlayer.Name);
            }

            ApplyMovesToState(moves, actingPlayer);

            opponent.ProcessOpponentMoves(moves);
        }