Commits

Alexander Regueiro committed 9fd4b96

Refactor and cleaned up arbiter program.
Arbiter program can now read from stdin directly.

  • Participants
  • Parent commits c4de62f

Comments (0)

Files changed (7)

+#!/bin/sh
+
+exit 0
+#!/bin/sh
+
+./bin/Icfp2011.Icrs.Player.exe $@

File src/ICFP-2011.sln

 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Icfp2011.Icrs.Player", "Icfp2011.Icrs.Player\Icfp2011.Icrs.Player.csproj", "{1413FC5A-C10C-459E-A9F7-40C0CBCFD184}"
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{4DDA0635-7AD8-497D-925C-E7065247F266}"
+	ProjectSection(SolutionItems) = preProject
+		..\install = ..\install
+		..\run = ..\run
+	EndProjectSection
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

File src/Icfp2011.Icrs.Arbiter/Program.cs

 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
 using System.Linq;
 using System.Text;
 
 {
     internal static class Program
     {
+        private static readonly string initialFuncText = LtgCards.ICombinator.ToName();
+
         public static int Main(string[] args)
         {
             try
             {
 #if DEBUG
                 Console.BufferHeight = 0xFFF;
+                Console.WindowHeight = 50;
 #endif
                 Console.Out.NewLine = "\n";
 
                 var optionArgs = args.Where(a => a.StartsWith("-")).ToArray();
                 var freeArgs = args.Except(optionArgs).ToArray();
 
-#if TEST
-                RunTestMatch();
-#else
-                if (freeArgs.Length == 1)
+                if (freeArgs.Length == 0)
+                {
+                    RunMatch();
+                }
+                else if (freeArgs.Length == 1)
                 {
                     RunMatch(args[0]);
                 }
                     Console.Error.WriteLine(Properties.Settings.Default.MessageNotEnoughArgs);
                     return Properties.Settings.Default.ExitCodeNotEnoughArgs;
                 }
-#endif
 
                 return Properties.Settings.Default.ExitCodeFatalError;
             }
         }
 #endif
 
+        public static void RunMatch()
+        {
+            try
+            {
+                var match = new LtgMatch();
+                while (true)
+                {
+                    StartTurn(match);
+                    while (true)
+                    {
+                        try
+                        {
+                            PerformCardAction(match, Console.In, false);
+                        }
+                        catch (FormatException)
+                        {
+                            Console.Error.WriteLine("Error reading input.");
+                            continue;
+                        }
+                        break;
+                    }
+                    if (!NextTurn(match, false))
+                        break;
+                }
+            }
+            catch (PlayerProgramTerminatedException)
+            {
+                HandlePlayerProcessEnded();
+            }
+        }
+
         public static void RunMatch(string playerProgramPath)
         {
             try
                 using (var playerAProcess = CreatePlayerProcess(playerProgramPath, 0))
                 {
                     var match = new LtgMatch();
-                    var turnIndex = 1;
-                    var initialFuncText = match.GetProponentSlots().First().Value.ToName();
-
                     while (true)
                     {
-                        var propSlots = match.GetProponentSlots();
-                        var oppSlots = match.GetOpponentSlots();
-
-                        Console.Out.WriteLine();
-                        Console.Out.WriteLine("###### turn {0}", turnIndex++);
-                        Console.Out.WriteLine("*** player {0}'s turn, with slots:",
-                            (int)match.CurrentPlayer);
-                        for (int i = 0; i < propSlots.Length; i++)
-                        {
-                            var slot = propSlots[i];
-                            var funcText = GetValueText(match, slot);
-                            if (slot.Vitality == LtgMatch.InitialVitality && funcText == initialFuncText)
-                                continue;
-                            Console.Out.WriteLine("{0}={{{1},{2}}}", i, slot.Vitality, funcText);
-                        }
-                        Console.Out.WriteLine("(slots {{{0},{1}}} are omitted)",
-                            LtgMatch.InitialVitality, initialFuncText);
-
-                        // Read card action from player program and perform it.
-                        var action = ReadCardAction(playerAProcess);
-                        var actionSlot = propSlots[action.SlotIndex];
-                        var applySuccess = false;
-                        if (action.ApplicationOrder == LtgCardApplicationOrder.Left)
-                        {
-                            applySuccess = actionSlot.ApplyLeft(propSlots, oppSlots, action.Card);
-                            Console.Out.WriteLine("player {0} applied card {1} to slot {2}",
-                                (int)match.CurrentPlayer, action.Card.ToName(), action.SlotIndex);
-                        }
-                        else if (action.ApplicationOrder == LtgCardApplicationOrder.Right)
-                        {
-                            applySuccess = actionSlot.ApplyRight(propSlots, oppSlots, action.Card);
-                            Console.Out.WriteLine("player {0} applied slot {2} to card {1}",
-                                (int)match.CurrentPlayer, action.Card.ToName(), action.SlotIndex);
-                        }
-                        else
-                        {
-                            throw new InvalidOperationException();
-                        }
-
-                        if (!applySuccess)
-                        {
-                            Console.Error.WriteLine("Exception");
-                            Console.Error.WriteLine("slot {0} reset to {1}", action.SlotIndex, initialFuncText);
-                        }
+                        StartTurn(match);
+                        PerformCardAction(match, playerAProcess.StandardOutput, true);
+                        if (!NextTurn(match, false))
+                            break;
                     }
                 }
             }
             catch (PlayerProgramTerminatedException)
             {
-                Console.Error.WriteLine();
-                Console.Error.WriteLine("Player program terminated.");
+                HandlePlayerProcessEnded();
             }
         }
 
         public static void RunMatch(string player1ProgramPath, string player2ProgramPath)
         {
-            using (var playerAProcess = CreatePlayerProcess(player1ProgramPath, LtgPlayer.PlayerA))
-            using (var playerBProcess = CreatePlayerProcess(player2ProgramPath, LtgPlayer.PlayerA))
+            try
             {
-                var match = new LtgMatch();
-                var initialFuncText = match.GetProponentSlots().First().Value.ToName();
+                using (var playerAProcess = CreatePlayerProcess(player1ProgramPath, LtgPlayer.PlayerA))
+                using (var playerBProcess = CreatePlayerProcess(player2ProgramPath, LtgPlayer.PlayerB))
+                {
+                    var match = new LtgMatch();
 
-                while (true)
-                {
-                    // TODO: run match for two players
+                    while (true)
+                    {
+                        StartTurn(match);
+                        PerformCardAction(match, playerAProcess.StandardOutput, true);
+                        PerformCardAction(match, playerBProcess.StandardOutput, true);
+                        if (!NextTurn(match, true))
+                            break;
+                    }
+                }
+            }
+            catch (PlayerProgramTerminatedException)
+            {
+                HandlePlayerProcessEnded();
+            }
+        }
 
-                    match.NextTurn();
-                }
+        private static void StartTurn(LtgMatch match)
+        {
+            Console.Out.WriteLine("###### turn {0}", match.TurnNumber);
+        }
+
+        private static bool NextTurn(LtgMatch match, bool switchTurns)
+        {
+            var success = match.NextTurn(switchTurns);
+            Console.Out.WriteLine();
+            return success;
+        }
+
+        private static void PerformCardAction(LtgMatch match, TextReader reader, bool echoInput)
+        {
+            var propSlots = match.GetProponentSlots();
+            var oppSlots = match.GetOpponentSlots();
+
+            Console.Out.WriteLine("*** player {0}'s turn, with slots:",
+                (int)match.CurrentPlayer);
+            for (int i = 0; i < propSlots.Length; i++)
+            {
+                var slot = propSlots[i];
+                var funcText = GetValueText(match, slot);
+                if (slot.Vitality == LtgMatch.InitialVitality && funcText == initialFuncText)
+                    continue;
+                Console.Out.WriteLine("{0}={{{1},{2}}}", i, slot.Vitality, funcText);
+            }
+            Console.Out.WriteLine("(slots {{{0},{1}}} are omitted)",
+                LtgMatch.InitialVitality, initialFuncText);
+
+            // Read card action from input stream and perform it.
+            var action = ReadCardAction(reader, echoInput);
+            var actionSlot = propSlots[action.SlotIndex];
+            var applySuccess = false;
+            if (action.ApplicationOrder == LtgCardApplicationOrder.Left)
+            {
+                applySuccess = actionSlot.ApplyLeft(propSlots, oppSlots, action.Card);
+                Console.Out.WriteLine("player {0} applied card {1} to slot {2}",
+                    (int)match.CurrentPlayer, action.Card.ToName(), action.SlotIndex);
+            }
+            else if (action.ApplicationOrder == LtgCardApplicationOrder.Right)
+            {
+                applySuccess = actionSlot.ApplyRight(propSlots, oppSlots, action.Card);
+                Console.Out.WriteLine("player {0} applied slot {2} to card {1}",
+                    (int)match.CurrentPlayer, action.Card.ToName(), action.SlotIndex);
+            }
+            else
+            {
+                throw new InvalidOperationException("Invalid card application order.");
+            }
+
+            if (!applySuccess)
+            {
+                Console.Error.WriteLine("Exception");
+                Console.Error.WriteLine("slot {0} reset to {1}", action.SlotIndex, initialFuncText);
             }
         }
 
         private static string GetValueTextInternal(LtgMatch match, LtgValue val)
         {
             var sb = new StringBuilder();
-            var funcs = new Stack<string>();
-            
+
             var testMatch = match;
             var evalDepth = 0;
             var evaluator = new LtgFunction((depth, propSlots, oppSlots, arg) =>
 
             var success = evaluator.Evaluate(ref evalDepth,
                 testMatch.GetProponentSlots(), testMatch.GetOpponentSlots(), val);
-
-            while (funcs.Count > 0)
-            {
-                var curFunc = funcs.Pop();
-                //sb.Append(curFunc + " ");
-            }
-            return sb.ToString().TrimEnd();
+            return sb.ToString();
         }
 
-        private static LtgAction ReadCardAction(Process playerProcess)
+        private static LtgAction ReadCardAction(TextReader reader, bool echoInput)
         {
             var action = new LtgAction();
 
             Func<string> readLine = () =>
                 {
-                    var line = playerProcess.StandardOutput.ReadLine();
-                    if (line == null)
+                    var line = reader.ReadLine();
+                    if (string.IsNullOrEmpty(line))
                         throw new PlayerProgramTerminatedException();
-                    Console.Out.WriteLine(line);
+                    if (echoInput)
+                        Console.Out.WriteLine(line);
                     return line;
                 };
             Action readSlotNumber = () =>
             return Process.Start(procStartInfo);
         }
 
+        private static void HandlePlayerProcessEnded()
+        {
+            Console.Error.WriteLine();
+            Console.Error.WriteLine("Player program terminated.");
+        }
+
         public class PlayerProgramTerminatedException : Exception
         {
             public PlayerProgramTerminatedException()

File src/Icfp2011.Icrs.Player/Program.cs

 
                 // TODO: temporary
 
+                WriteCardAction(new LtgAction()
+                    {
+                        ApplicationOrder = LtgCardApplicationOrder.Right,
+                        SlotIndex = 0,
+                        Card = LtgCards.SCombinator,
+                    });
+                WriteCardAction(new LtgAction()
+                    {
+                        ApplicationOrder = LtgCardApplicationOrder.Right,
+                        SlotIndex = 0,
+                        Card = LtgCards.Get,
+                    });
+                WriteCardAction(new LtgAction()
+                    {
+                        ApplicationOrder = LtgCardApplicationOrder.Right,
+                        SlotIndex = 0,
+                        Card = LtgCards.ICombinator,
+                    });
+                WriteCardAction(new LtgAction()
+                    {
+                        ApplicationOrder = LtgCardApplicationOrder.Right,
+                        SlotIndex = 0,
+                        Card = LtgCards.Zero,
+                    });
+
                 //WriteCardAction(new LtgAction()
                 //    {
                 //        ApplicationOrder = LtgCardApplicationOrder.Right,
                 //        SlotIndex = 0,
-                //        Card = LtgCards.SCombinator,
-                //    });
-                //WriteCardAction(new LtgAction()
-                //    {
-                //        ApplicationOrder = LtgCardApplicationOrder.Right,
-                //        SlotIndex = 0,
-                //        Card = LtgCards.Get,
-                //    });
-                //WriteCardAction(new LtgAction()
-                //    {
-                //        ApplicationOrder = LtgCardApplicationOrder.Right,
-                //        SlotIndex = 0,
-                //        Card = LtgCards.ICombinator,
+                //        Card = LtgCards.Help,
                 //    });
                 //WriteCardAction(new LtgAction()
                 //    {
                 //        SlotIndex = 0,
                 //        Card = LtgCards.Zero,
                 //    });
-
-                WriteCardAction(new LtgAction()
-                    {
-                        ApplicationOrder = LtgCardApplicationOrder.Right,
-                        SlotIndex = 0,
-                        Card = LtgCards.Help,
-                    });
-                WriteCardAction(new LtgAction()
-                    {
-                        ApplicationOrder = LtgCardApplicationOrder.Right,
-                        SlotIndex = 0,
-                        Card = LtgCards.Zero,
-                    });
-                WriteCardAction(new LtgAction()
-                    {
-                        ApplicationOrder = LtgCardApplicationOrder.Left,
-                        SlotIndex = 0,
-                        Card = LtgCards.KCombinator,
-                    });
+                //WriteCardAction(new LtgAction()
+                //    {
+                //        ApplicationOrder = LtgCardApplicationOrder.Left,
+                //        SlotIndex = 0,
+                //        Card = LtgCards.KCombinator,
+                //    });
             }
 #if !DEBUG
             catch (Exception ex)

File src/Icfp2011.Icrs/LtgFunction.cs

         public IList<LtgValue> Arguments
         {
             get { return this.args; }
-            //set { this.args = value; }
         }
 #endif
 
                 return null;
 
             depth++;
-            var result = this.func(depth, propSlots, oppSlots, arg);
-//#if DEBUG
-//            var resFunc = result as LtgFunction;
-//            if (resFunc != null)
-//            {
-//                resFunc.Arguments = new[] { arg };
-//            }
-//#endif
-            return result;
+            return this.func(depth, propSlots, oppSlots, arg);
         }
     }
 }

File src/Icfp2011.Icrs/LtgMatch.cs

     {
         public const int NumSlots = 256;
         public const int InitialVitality = 10000;
+        public const int MaxNumTurns = 100000;
 
-        // Slots of both players.
+        public static readonly LtgValue InitialSlotValue = LtgCards.ICombinator;
+
         private LtgSlot[] slotsPlayerA;
         private LtgSlot[] slotsPlayerB;
 
-        // Player whose turn it currently is.
         private LtgPlayer curPlayer;
 
+        private int turnNumber;
+
         public LtgMatch()
         {
             this.slotsPlayerA = new LtgSlot[NumSlots];
             this.slotsPlayerB = new LtgSlot[NumSlots];
 
             this.curPlayer = LtgPlayer.PlayerA;
+            this.turnNumber = 1;
 
             Initialize();
         }
             this.curPlayer = curPlayer;
         }
 
+        public int TurnNumber
+        {
+            get { return this.turnNumber; }
+        }
+
         public LtgPlayer CurrentPlayer
         {
             get { return this.curPlayer; }
         {
             for (int i = 0; i < NumSlots; i++)
             {
-                this.slotsPlayerA[i] = new LtgSlot(InitialVitality, LtgCards.ICombinator);
-                this.slotsPlayerB[i] = new LtgSlot(InitialVitality, LtgCards.ICombinator);
+                this.slotsPlayerA[i] = new LtgSlot(InitialVitality, InitialSlotValue);
+                this.slotsPlayerB[i] = new LtgSlot(InitialVitality, InitialSlotValue);
             }
         }
 
                 throw new InvalidOperationException();
         }
 
-        public void NextTurn()
+        // Returns whether match can continue.
+        public bool NextTurn(bool switchTurns)
         {
-            if (this.curPlayer == LtgPlayer.PlayerA)
-                this.curPlayer = LtgPlayer.PlayerB;
-            else if (this.curPlayer == LtgPlayer.PlayerB)
-                this.curPlayer = LtgPlayer.PlayerA;
-            else
-                throw new InvalidOperationException();
+            if (switchTurns)
+            {
+                if (this.curPlayer == LtgPlayer.PlayerA)
+                    this.curPlayer = LtgPlayer.PlayerB;
+                else if (this.curPlayer == LtgPlayer.PlayerB)
+                    this.curPlayer = LtgPlayer.PlayerA;
+                else
+                    throw new InvalidOperationException();
+            }
+
+            this.turnNumber++;
+            return this.turnNumber < MaxNumTurns;
         }
 
         public LtgMatch Clone()