diff --git a/Program.cs b/Program.cs index 718f5e7..17e60c8 100644 --- a/Program.cs +++ b/Program.cs @@ -1,6 +1,7 @@ using AmazeingEvening; using Grpc.Core; using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -8,19 +9,23 @@ namespace gRPCGuide { class Program { + private static CallOptions _options; + private static Maze.MazeClient _mazeClient; + + /// MakeRequest is a helper function, that ensures the authorization header is sent in each communication with the server + static Task MakeRequest(Func > requestFunc, TReq requestPayload) => + requestFunc(requestPayload, _options).ResponseAsync; static async Task Main(string[] args) { var channel = new Channel(host: "10.100.100.100", port: 5001, ChannelCredentials.Insecure); - var options = new CallOptions(headers: new Metadata { { "Authorization", args.FirstOrDefault() ?? throw new Exception("Key?") } }); + _options = new CallOptions(headers: new Metadata { { "Authorization", args.FirstOrDefault() ?? throw new Exception("Key?") } }); var playerClient = new Player.PlayerClient(channel); var mazesClient = new Mazes.MazesClient(channel); - var mazeClient = new Maze.MazeClient(channel); - /// MakeRequest is a helper function, that ensures the authorization header is sent in each communication with the server - Task MakeRequest(Func > requestFunc, TReq requestPayload) => - requestFunc(requestPayload, options).ResponseAsync; + await MakeRequest(playerClient.ForgetMeAsync, new ForgetMeRequest()); + Console.WriteLine("Forgot myself"); /// Register ourselves var ourName = $"deBoerIsTroef"; @@ -30,9 +35,205 @@ Task MakeRequest(Func crawlCrumbs = new Stack(); + List> _collectCrumbs = new List>(); + List> _exitCrumbs = new List>(); + + if (!didKonami) + { + options = (await MakeMove(MoveDirection.Up, _exitCrumbs, _collectCrumbs, crawlCrumbs)) ?? options; + options = (await MakeMove(MoveDirection.Up, _exitCrumbs, _collectCrumbs, crawlCrumbs)) ?? options; + options = (await MakeMove(MoveDirection.Down, _exitCrumbs, _collectCrumbs, crawlCrumbs)) ?? options; + options = (await MakeMove(MoveDirection.Down, _exitCrumbs, _collectCrumbs, crawlCrumbs)) ?? options; + options = (await MakeMove(MoveDirection.Left, _exitCrumbs, _collectCrumbs, crawlCrumbs)) ?? options; + options = (await MakeMove(MoveDirection.Right, _exitCrumbs, _collectCrumbs, crawlCrumbs)) ?? options; + options = (await MakeMove(MoveDirection.Left, _exitCrumbs, _collectCrumbs, crawlCrumbs)) ?? options; + options = (await MakeMove(MoveDirection.Right, _exitCrumbs, _collectCrumbs, crawlCrumbs)) ?? options; + didKonami = true; + } + + while (true) + { + TrackExits(options, _exitCrumbs); + if (options.CurrentScoreInHand == 0 && options.CurrentScoreInBag >= maze.PotentialReward) + { + // Looking for exit! + if (options.CanExitMazeHere) + { + await MakeRequest(_mazeClient.ExitMazeAsync, new ExitMazeRequest()); + return; + } + // Looking for collection point! + var stack = _exitCrumbs.OrderBy(st => st.Count).FirstOrDefault(); + if (stack == null) + { + continue; + } + + var dir = stack.Peek(); + var step = ReverseDir(dir); + options = await MakeMove(step, _exitCrumbs, _collectCrumbs, crawlCrumbs); + continue; + } + + TrackCollectionPoints(options, _collectCrumbs); + if (options.CurrentScoreInHand + options.CurrentScoreInBag >= maze.PotentialReward) + { + if (options.CanCollectScoreHere) + { + options = (await MakeRequest(_mazeClient.CollectScoreAsync, new CollectScoreRequest())).PossibleActionsAndCurrentScore; + continue; + } + + // Looking for collection point! + var stack = _collectCrumbs.OrderBy(st => st.Count).FirstOrDefault(); + if (stack == null) + { + continue; + } + + var dir = stack.Peek(); + var step = ReverseDir(dir); + options = await MakeMove(step, _exitCrumbs, _collectCrumbs, crawlCrumbs); + continue; + } + + // Collecting + var mostUsefulDirection = MostUsefulDir(options, maze); + if (mostUsefulDirection != null) + { + options = await MakeMove(mostUsefulDirection.Direction, _exitCrumbs, _collectCrumbs, crawlCrumbs); + continue; + } + + if (crawlCrumbs.Any()) + { + var dir = ReverseDir(crawlCrumbs.Peek()); + options = await MakeMove(dir, _exitCrumbs, _collectCrumbs, crawlCrumbs); + continue; + } + + Console.WriteLine("Stuck!"); + continue; + } + + } + + private static void TrackExits(PossibleActionsAndCurrentScore options, List> exitCrumbs) + { + foreach (var dir in options.MoveActions.Where(ma => ma.AllowsExit)) + { + var stack = new Stack(); + stack.Push(ReverseDir(dir.Direction)); + exitCrumbs.Add(stack); + } + } + + private static void TrackCollectionPoints(PossibleActionsAndCurrentScore options, List> collectCrumbs) + { + foreach (var dir in options.MoveActions.Where(ma => ma.AllowsScoreCollection)) + { + var stack = new Stack(); + stack.Push(ReverseDir(dir.Direction)); + collectCrumbs.Add(stack); + } + } + + private static async Task MakeMove(MoveDirection direction, List> exitCrumbs, List> collectCrumbs, Stack crumbs) + { + try + { + var retVal = (await MakeRequest(_mazeClient.MoveAsync, new MoveRequest {Direction = direction})) + .PossibleActionsAndCurrentScore; + if (retVal == null) + throw new ArgumentException(); + + foreach (var st in exitCrumbs) + Push(st, direction); + + foreach (var st in collectCrumbs) + Push(st, direction); + + Push(crumbs, direction); + + return retVal; + } + catch (Exception e) + { + Console.WriteLine(e.Message); + return null; + } + } + + private static MoveAction MostUsefulDir(PossibleActionsAndCurrentScore options, MazeInfo mazeInfo) + { +/* if (options.CurrentScoreInHand > 0 && + options.CurrentScoreInHand + options.CurrentScoreInBag >= mazeInfo.PotentialReward) + { + var collectionPoint = options.MoveActions.FirstOrDefault(ma => ma.AllowsScoreCollection); + if (collectionPoint != null) + return collectionPoint; + } + + if (options.CurrentScoreInBag >= mazeInfo.PotentialReward) + { + var exit = options.MoveActions.FirstOrDefault(ma => ma.AllowsExit); + if (exit != null) + return exit; + }*/ + + var mostUsefulDir = options.MoveActions.Where(ma => !ma.HasBeenVisited) + .OrderBy(ma => ma.AllowsScoreCollection) + .ThenBy(ma => ma.AllowsExit) + .ThenByDescending(ma => ma.Reward) + .FirstOrDefault(); + return mostUsefulDir; + } + + static void Push(Stack stack, MoveDirection dir) + { + if (stack.Count == 0) + { + stack.Push(dir); + return; + } + + if (stack.Count != 0 && stack.Peek() == ReverseDir(dir)) + stack.Pop(); + else + stack.Push(dir); + } + + private static MoveDirection ReverseDir(MoveDirection bestDir) + { + switch (bestDir) + { + case MoveDirection.Down: return MoveDirection.Up; + case MoveDirection.Up: return MoveDirection.Down; + case MoveDirection.Left :return MoveDirection.Right; + case MoveDirection.Right: return MoveDirection.Left; + default: + throw new ArgumentException("Bad dir"); + } } } }