Skip to content

Commit

Permalink
Pretty smart algo
Browse files Browse the repository at this point in the history
  • Loading branch information
boekabart committed Sep 25, 2019
1 parent de3623a commit 1ad5632
Showing 1 changed file with 209 additions and 8 deletions.
217 changes: 209 additions & 8 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
using AmazeingEvening;
using Grpc.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

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<TResp> MakeRequest<TReq, TResp>(Func<TReq, CallOptions, AsyncUnaryCall<TResp> > 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<TResp> MakeRequest<TReq, TResp>(Func<TReq, CallOptions, AsyncUnaryCall<TResp> > requestFunc, TReq requestPayload) =>
requestFunc(requestPayload, options).ResponseAsync;
await MakeRequest(playerClient.ForgetMeAsync, new ForgetMeRequest());
Console.WriteLine("Forgot myself");

/// Register ourselves
var ourName = $"deBoerIsTroef";
Expand All @@ -30,9 +35,205 @@ Task<TResp> MakeRequest<TReq, TResp>(Func<TReq, CallOptions, AsyncUnaryCall<TRes
/// List all the available mazes
var availableMazesResult = await MakeRequest(mazesClient.GetAllAvailableMazesAsync, new GetAllAvailableMazesRequest());
foreach (var maze in availableMazesResult.AvailableMazes)
Console.WriteLine($"Maze [{maze.Name}] | Total tiles: [{maze.TotalTiles}] | Potential reward: [{maze.PotentialReward}]");

await channel.ShutdownAsync();
{
Console.WriteLine(
$"Maze [{maze.Name}] | Total tiles: [{maze.TotalTiles}] | Potential reward: [{maze.PotentialReward}]");
await DoMaze(maze, channel);

}


await channel.ShutdownAsync();
}

private static bool didKonami = false;

private static async Task DoMaze(MazeInfo maze, Channel channel)
{
_mazeClient = new Maze.MazeClient(channel);
var response = await MakeRequest(_mazeClient.EnterMazeAsync, new EnterMazeRequest { MazeName = maze.Name});
var options = response.PossibleActionsAndCurrentScore;

Stack<MoveDirection> crawlCrumbs = new Stack<MoveDirection>();
List<Stack<MoveDirection>> _collectCrumbs = new List<Stack<MoveDirection>>();
List<Stack<MoveDirection>> _exitCrumbs = new List<Stack<MoveDirection>>();

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<Stack<MoveDirection>> exitCrumbs)
{
foreach (var dir in options.MoveActions.Where(ma => ma.AllowsExit))
{
var stack = new Stack<MoveDirection>();
stack.Push(ReverseDir(dir.Direction));
exitCrumbs.Add(stack);
}
}

private static void TrackCollectionPoints(PossibleActionsAndCurrentScore options, List<Stack<MoveDirection>> collectCrumbs)
{
foreach (var dir in options.MoveActions.Where(ma => ma.AllowsScoreCollection))
{
var stack = new Stack<MoveDirection>();
stack.Push(ReverseDir(dir.Direction));
collectCrumbs.Add(stack);
}
}

private static async Task<PossibleActionsAndCurrentScore> MakeMove(MoveDirection direction, List<Stack<MoveDirection>> exitCrumbs, List<Stack<MoveDirection>> collectCrumbs, Stack<MoveDirection> 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<MoveDirection> 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");
}
}
}
}

0 comments on commit 1ad5632

Please sign in to comment.