1. Alexander Regueiro
  2. ICFP 2011 ICRS

Source

ICFP 2011 ICRS / src / Icfp2011.Icrs.Player / Program.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Icfp2011.Icrs.Player
{
    using Bot;

    internal static class Program
    {
        private static LtgBot playerBot;

        // arg 0 = path to bot file
        // arg 1 = 0/1 indicating which player this is
        public static int Main(string[] args)
        {
            try
            {
#if LAUNCH_DEBUG
                Debugger.Launch();
#endif

                Console.Out.NewLine = "\n";

                var optionArgs = args.Where(a => a.StartsWith("-")).ToArray();
                var freeArgs = args.Except(optionArgs).ToArray();

                if (freeArgs.Length < 2)
                {
#if DEBUG
                    Console.Error.WriteLine(Properties.Settings.Default.MessageNotEnoughArgs);
#endif
                    return Properties.Settings.Default.ExitCodeNotEnoughArgs;
                }

                var botProgramPath = freeArgs[0];
                LoadBot(botProgramPath);

                var programPlayer = (LtgPlayer)int.Parse(freeArgs[1]);
                var singlePlayerMode = optionArgs.Contains("-single", StringComparer.InvariantCultureIgnoreCase);
                RunPlayer(programPlayer, singlePlayerMode);

                return Properties.Settings.Default.ExitCodeSuccess;
            }
#if !DEBUG
            catch (Exception ex)
            {
                Console.Error.WriteLine(Properties.Settings.Default.MessageFatalError, ex.Message);
                return Properties.Settings.Default.ExitCodeFatalError;
            }
#endif
            finally
            {
            }
        }

        private static void LoadBot(string path)
        {
            var assembly = Assembly.LoadFrom(path);
            var botType = assembly.GetTypes().Single(t => typeof(LtgBot).IsAssignableFrom(t));
            playerBot = (LtgBot)Activator.CreateInstance(botType);
        }

        private static void RunPlayer(LtgPlayer player, bool singlePlayerMode)
        {
            var match = new LtgMatch();

#if DEBUG
            Console.Error.WriteLine("I am player {0}.", player);
#endif

            playerBot.Start();
            if (player != match.CurrentPlayer)
                DoOpponentAction(match);
            while (true)
            {
                match.StartPlayerTurn();
                DoProponentAction(match);
                if (!singlePlayerMode)
                {
                    match.SwitchPlayerTurn();
                    match.StartPlayerTurn();
                    DoOpponentAction(match);
                    match.SwitchPlayerTurn();
                }

                match.NextTurn();
            }
        }

        private static void DoProponentAction(LtgMatch match)
        {
            var action = playerBot.DoAction();
            WriteCardAction(action);
            DoAction(match, action);
            playerBot.OnProponentAction(action);
        }

        private static void DoOpponentAction(LtgMatch match)
        {
            playerBot.OnOpponentThinking();
            var action = ReadCardAction();
            DoAction(match, action);
            playerBot.OnOpponentAction(action);
        }

        private static void DoAction(LtgMatch match, LtgAction action)
        {
            if (action.Card == null)
            {
#if DEBUG
                Console.Error.WriteLine("{0}: invalid card", match.CurrentPlayer);
#endif
                return;
            }

            var propSlots = match.GetProponentSlots();
            var oppSlots = match.GetOpponentSlots();
            var slot = propSlots[action.SlotIndex];
            LtgException result;
            slot.DoAction(propSlots, oppSlots, action, out result);

#if DEBUG
            Console.Error.WriteLine("{0}: {1} {2} {3}", match.CurrentPlayer,
                action.ApplyOrder, action.Card.ToName(), action.SlotIndex);
#endif
        }

        private static void WriteCardAction(LtgAction action)
        {
            Action writeSlotNumber = () => Console.Out.WriteLine(action.SlotIndex);
            Action writeCardName = () => Console.Out.WriteLine(action.Card.ToName());

            Console.Out.WriteLine((int)action.ApplyOrder);
            if (action.ApplyOrder == LtgCardApplyOrder.Left)
            {
                writeCardName();
                writeSlotNumber();
            }
            else if (action.ApplyOrder == LtgCardApplyOrder.Right)
            {
                writeSlotNumber();
                writeCardName();
            }
            else
            {
                throw new ArgumentException("Invalid action.", "action");
            }
        }

        private static LtgAction ReadCardAction()
        {
            var action = new LtgAction();

            Action readSlotNumber = () => action.SlotIndex = int.Parse(Console.In.ReadLine());
            Action readCardName = () => action.Card = LtgCards.FromName(Console.In.ReadLine());

            action.ApplyOrder = (LtgCardApplyOrder)int.Parse(Console.In.ReadLine());
            if (action.ApplyOrder == LtgCardApplyOrder.Left)
            {
                readCardName();
                readSlotNumber();
            }
            else if (action.ApplyOrder == LtgCardApplyOrder.Right)
            {
                readSlotNumber();
                readCardName();
            }
            else
            {
                throw new InvalidOperationException("Invalid application order.");
            }

            return action;
        }
    }
}