From fbded5932f28bc9e038999e94d073816dda03acb Mon Sep 17 00:00:00 2001 From: Rob Date: Tue, 11 Jul 2023 20:30:49 +0200 Subject: [PATCH] Started readme.md, WIP commit for collecting all rewards --- Bobo.System.Maze.Bot/Bot.cs | 3 +- Bobo.System.Maze.Bot/BumbBot.cs | 55 ++++++ Bobo.System.Maze.Bot/BumpBot.cs | 47 ----- Bobo.System.Maze.Bot/Interface/BaseBot.cs | 20 +++ Bobo.System.Maze.Bot/SimpleBot.cs | 165 +++++++++++++----- Bobo.System.Maze.Bot/SimplerBot.cs | 51 +++--- .../Bobo.System.Maze.Console.csproj | 0 .../Program.cs | 5 +- Bobo.Systems.Maze.sln => Bobo.System.Maze.sln | 7 +- readme.md | 6 + 10 files changed, 237 insertions(+), 122 deletions(-) create mode 100644 Bobo.System.Maze.Bot/BumbBot.cs delete mode 100644 Bobo.System.Maze.Bot/BumpBot.cs create mode 100644 Bobo.System.Maze.Bot/Interface/BaseBot.cs rename {Bobo.Systems.Maze.Console => Bobo.System.Maze.Console}/Bobo.System.Maze.Console.csproj (100%) rename {Bobo.Systems.Maze.Console => Bobo.System.Maze.Console}/Program.cs (94%) rename Bobo.Systems.Maze.sln => Bobo.System.Maze.sln (81%) create mode 100644 readme.md diff --git a/Bobo.System.Maze.Bot/Bot.cs b/Bobo.System.Maze.Bot/Bot.cs index 7822bb7..82509de 100644 --- a/Bobo.System.Maze.Bot/Bot.cs +++ b/Bobo.System.Maze.Bot/Bot.cs @@ -1,5 +1,4 @@ -using Bobo.System.Maze.Bot; -using Bobo.Systems.Maze.Console.Model; +using Bobo.Systems.Maze.Console.Model; using HightechICT.Amazeing.Client.Rest; using System.Collections.ObjectModel; using LogConsole = System.Console; diff --git a/Bobo.System.Maze.Bot/BumbBot.cs b/Bobo.System.Maze.Bot/BumbBot.cs new file mode 100644 index 0000000..1c0da65 --- /dev/null +++ b/Bobo.System.Maze.Bot/BumbBot.cs @@ -0,0 +1,55 @@ +using Bobo.System.Maze.Bot.Interface; +using HightechICT.Amazeing.Client.Rest; +using Microsoft.Extensions.Logging; + +namespace Bobo.System.Maze.Bot +{ + public class BumbBot : BaseBot + { + public BumbBot(AmazeingClient mazeClient, ILogger logger) : base(mazeClient, logger) + { } + + public override async Task Run(MazeInfo maze) + { + if (MazeClient == null) + throw new ArgumentException(nameof(MazeClient)); + + if (string.IsNullOrWhiteSpace(maze.Name)) + throw new ArgumentException(nameof(maze.Name)); + + Random random = new Random(); + Logger.Log(LogLevel.Information, "Entering maze '{MazeName}'", maze.Name); + PossibleActionsAndCurrentScore result = await MazeClient.EnterMaze(maze.Name); + + do + { + // select a way to go + MoveAction[] moves = result.PossibleMoveActions.ToArray(); + MoveAction[] notExploredMoves = moves.Any(m => !m.HasBeenVisited) ? moves.Where(m => !m.HasBeenVisited).ToArray() : moves; + + if (moves.All(m => m.HasBeenVisited)) + { + Logger.Log(LogLevel.Debug, "All adjacent tiles have been visited! Selecting next path random."); + } + else + { + Logger.Log(LogLevel.Debug, $"{string.Join(", ", notExploredMoves.Select(m => m.Direction.ToString()))} have not been visited, selecting next move."); + } + + int selected = random.Next(notExploredMoves.Length - 1); + MoveAction moveAction = notExploredMoves[selected]; + + Logger.Log(LogLevel.Debug, $"Moving {moveAction.Direction}, I have {(!moveAction.HasBeenVisited ? "not" : string.Empty)} been here."); + result = await MazeClient.Move(moveAction.Direction); + Logger.Log(LogLevel.Debug, $"New tile has {(!result.CanExitMazeHere ? "no" : string.Empty)} exit."); + + } while (!result.CanExitMazeHere); + + await MazeClient.ExitMaze(); + + Logger.Log(LogLevel.Information, $"Exited the maze!"); + + return 0; + } + } +} diff --git a/Bobo.System.Maze.Bot/BumpBot.cs b/Bobo.System.Maze.Bot/BumpBot.cs deleted file mode 100644 index 41c76f3..0000000 --- a/Bobo.System.Maze.Bot/BumpBot.cs +++ /dev/null @@ -1,47 +0,0 @@ -using HightechICT.Amazeing.Client.Rest; -using LogConsole = System.Console; - -namespace Bobo.System.Maze.Bot -{ - public class BumpBot - { - public static async Task Run(string mazeName, AmazeingClient mazeClient) - { - Random random = new Random(); - LogConsole.WriteLine($"Entering maze '{mazeName}'"); - PossibleActionsAndCurrentScore result = await mazeClient.EnterMaze(mazeName); - - do - { - await Task.Delay(100); - // select a way to go - MoveAction[] moves = result.PossibleMoveActions.ToArray(); - MoveAction[] notExploredMoves = moves.Any(m => !m.HasBeenVisited) ? moves.Where(m => !m.HasBeenVisited).ToArray() : moves; - - if (moves.All(m => m.HasBeenVisited)) - { - LogConsole.WriteLine("All adjacent tiles have been visited! Selecting next path random."); - } - else - { - LogConsole.WriteLine($"{string.Join(", ", notExploredMoves.Select(m => m.Direction.ToString()))} have not been visited, selecting next move."); - } - - int selected = random.Next(notExploredMoves.Length - 1); - - MoveAction moveAction = notExploredMoves[selected]; - - LogConsole.WriteLine($"Moving {moveAction.Direction}, I have {(!moveAction.HasBeenVisited ? "not" : string.Empty)} been here."); - - result = await mazeClient.Move(moveAction.Direction); - - LogConsole.WriteLine($"New tile has {(!result.CanExitMazeHere ? "no" : string.Empty)} exit."); - - } while (!result.CanExitMazeHere); - - await mazeClient.ExitMaze(); - - LogConsole.WriteLine($"Exited the maze!"); - } - } -} diff --git a/Bobo.System.Maze.Bot/Interface/BaseBot.cs b/Bobo.System.Maze.Bot/Interface/BaseBot.cs new file mode 100644 index 0000000..f0557ca --- /dev/null +++ b/Bobo.System.Maze.Bot/Interface/BaseBot.cs @@ -0,0 +1,20 @@ +using HightechICT.Amazeing.Client.Rest; +using Microsoft.Extensions.Logging; + +namespace Bobo.System.Maze.Bot.Interface +{ + public abstract class BaseBot + { + protected ILogger Logger { get; } + + protected AmazeingClient MazeClient { get; } + + public BaseBot(AmazeingClient mazeClient, ILogger logger) + { + MazeClient = mazeClient; + Logger = logger; + } + + public abstract Task Run(MazeInfo maze); + } +} diff --git a/Bobo.System.Maze.Bot/SimpleBot.cs b/Bobo.System.Maze.Bot/SimpleBot.cs index 1d1fa24..74327d5 100644 --- a/Bobo.System.Maze.Bot/SimpleBot.cs +++ b/Bobo.System.Maze.Bot/SimpleBot.cs @@ -1,84 +1,159 @@ -using HightechICT.Amazeing.Client.Rest; +using Bobo.System.Maze.Bot.Interface; +using HightechICT.Amazeing.Client.Rest; using Microsoft.Extensions.Logging; -using LogConsole = System.Console; - namespace Bobo.System.Maze.Bot { - public class SimpleBot + public class SimpleBot : BaseBot { - public static async Task Run(MazeInfo maze, AmazeingClient mazeClient, ILogger logger) + private Stack Directions { get; set; } = new Stack(); + private List> ExitDirections { get; set; } = new List>(); + private List> CollectionPointDirections { get; set; } = new List>(); + + public SimpleBot(AmazeingClient mazeClient, ILogger logger) : base(mazeClient, logger) + { } + + public override async Task Run(MazeInfo maze) { - if (mazeClient == null) - throw new ArgumentException(nameof(mazeClient)); + if (MazeClient == null) + throw new ArgumentException(nameof(MazeClient)); if (string.IsNullOrWhiteSpace(maze.Name)) throw new ArgumentException(nameof(maze.Name)); Random random = new Random(); - logger.Log(LogLevel.Information, "Entering maze '{MazeName}'", maze.Name); - PossibleActionsAndCurrentScore result = await mazeClient.EnterMaze(maze.Name); - Stack directions = new Stack(); + Logger.Log(LogLevel.Information, "Entering maze '{MazeName}'", maze.Name); + PossibleActionsAndCurrentScore result = await MazeClient.EnterMaze(maze.Name); int collected = 0; do { if (result.PossibleMoveActions.All(m => m.HasBeenVisited)) { - logger.Log(LogLevel.Debug, "All adjacent tiles have been visited! Going back."); - Direction direction = directions.Pop(); - - switch (direction) - { - case Direction.Left: - direction = Direction.Right; - break; - case Direction.Right: - direction = Direction.Left; - break; - case Direction.Up: - direction = Direction.Down; - break; - case Direction.Down: - direction = Direction.Up; - break; - - } - - logger.Log(LogLevel.Debug, "Moving {Direction}, I have been here.", direction); - - result = await mazeClient.Move(direction); + Logger.Log(LogLevel.Debug, "All adjacent tiles have been visited! Going back."); + result = await MoveBackOne(); } else { MoveAction[] notVisited = result.PossibleMoveActions.Where(m => !m.HasBeenVisited).ToArray(); - logger.Log(LogLevel.Debug, $"{string.Join(", ", notVisited.Select(m => m.Direction.ToString()))} have not been visited, selecting next move."); + Logger.Log(LogLevel.Debug, $"{string.Join(", ", notVisited.Select(m => m.Direction.ToString()))} have not been visited, selecting next move."); int selected = random.Next(notVisited.Length - 1); MoveAction moveAction = notVisited[selected]; - logger.Log(LogLevel.Debug, $"Moving {moveAction.Direction}, I have {(!moveAction.HasBeenVisited ? "not" : string.Empty)} been here."); + Logger.Log(LogLevel.Debug, $"Moving {moveAction.Direction}, I have {(!moveAction.HasBeenVisited ? "not" : string.Empty)} been here."); - result = await mazeClient.Move(moveAction.Direction); + result = await MazeClient.Move(moveAction.Direction); - directions.Push(moveAction.Direction); + Directions.Push(moveAction.Direction); } - if (result.CanCollectScoreHere && result.CurrentScoreInHand > 0) + + // if this is an exit, copy the path so we know how to get there + if (result.CanExitMazeHere) + { + ExitDirections.Add(new List(Directions)); + } + + // if this is a collection point, copy the path so we know how to get there + if (result.CanCollectScoreHere) + { + CollectionPointDirections.Add(new List(Directions)); + + List list = new List(Directions); + } + + Logger.Log(LogLevel.Debug, $"New tile has {(!result.CanExitMazeHere ? "no" : string.Empty)} exit."); + + } while (maze.PotentialReward != result.CurrentScoreInHand + && CollectionPointDirections.Any() + && ExitDirections.Any()); + + + + do + { + // create a list of the directions to the current point + List fromStart = new List(Directions); + + // see what collection point is closest (if multiple) + List collectionPointDirections = CollectionPointDirections.First(); + int collectionCommonPointFromStart = int.MaxValue; + foreach(List cdp in CollectionPointDirections) + { + int lowest = fromStart.Count() < cdp.Count() ? fromStart.Count() : cdp.Count(); + int lastCommonIndex = 0; + + // start from index 0 and work up to the lowest size + for (lastCommonIndex = 0; lastCommonIndex < lowest; lastCommonIndex++) + { + if (fromStart[lastCommonIndex] != cdp[lastCommonIndex]) + { + // not common, break loop + break; + } + } + + if (lastCommonIndex < collectionCommonPointFromStart) + { + collectionPointDirections = cdp; + collectionCommonPointFromStart = lastCommonIndex; + } + } + + // first go back to the common index + for (int returnMoves = 0; returnMoves < fromStart.Count - collectionCommonPointFromStart; returnMoves ++) + { + await MoveBackOne(); + } + + for (int toCollectionIndex = collectionCommonPointFromStart + 1; toCollectionIndex < collectionPointDirections.Count(); toCollectionIndex++) + { + result = await MazeClient.Move(collectionPointDirections[toCollectionIndex]); + } + + // go to collection + if (result.CanCollectScoreHere) { collected += result.CurrentScoreInHand; - await mazeClient.CollectScore(); + await MazeClient.CollectScore(); } - logger.Log(LogLevel.Debug, $"New tile has {(!result.CanExitMazeHere ? "no" : string.Empty)} exit."); + // go to exit + } + while (!result.CanExitMazeHere); - } while (!result.CanExitMazeHere); + await MazeClient.ExitMaze(); - await mazeClient.ExitMaze(); - - logger.Log(LogLevel.Information, "Collected {Collected}!", collected); - logger.Log(LogLevel.Information, "Exited maze {MazeName}!", maze.Name); + Logger.Log(LogLevel.Information, "Collected {Collected}!", collected); + Logger.Log(LogLevel.Information, "Exited maze {MazeName}!", maze.Name); return collected; } + + private Task MoveBackOne() + { + Direction direction = Directions.Pop(); + + switch (direction) + { + case Direction.Left: + direction = Direction.Right; + break; + case Direction.Right: + direction = Direction.Left; + break; + case Direction.Up: + direction = Direction.Down; + break; + case Direction.Down: + direction = Direction.Up; + break; + + } + + Logger.Log(LogLevel.Debug, "Moving {Direction}, I have been here.", direction); + + return MazeClient.Move(direction); + } } } diff --git a/Bobo.System.Maze.Bot/SimplerBot.cs b/Bobo.System.Maze.Bot/SimplerBot.cs index ea81848..1fbb504 100644 --- a/Bobo.System.Maze.Bot/SimplerBot.cs +++ b/Bobo.System.Maze.Bot/SimplerBot.cs @@ -1,32 +1,33 @@ -using HightechICT.Amazeing.Client.Rest; -using LogConsole = System.Console; - +using Bobo.System.Maze.Bot.Interface; +using HightechICT.Amazeing.Client.Rest; +using Microsoft.Extensions.Logging; namespace Bobo.System.Maze.Bot { - public class SimplerBot + public class SimplerBot : BaseBot { - public static async Task Run(string mazeName, AmazeingClient mazeClient) - { - if (mazeClient == null) - throw new ArgumentException(nameof(mazeClient)); + public SimplerBot(AmazeingClient mazeClient, ILogger logger) : base(mazeClient, logger) + { } - if (string.IsNullOrWhiteSpace(mazeName)) - throw new ArgumentException(nameof(mazeName)); + public override async Task Run(MazeInfo maze) + { + if (MazeClient == null) + throw new ArgumentException(nameof(MazeClient)); + + if (string.IsNullOrWhiteSpace(maze.Name)) + throw new ArgumentException(nameof(maze.Name)); Random random = new Random(); - LogConsole.WriteLine($"Entering maze '{mazeName}'"); - PossibleActionsAndCurrentScore result = await mazeClient.EnterMaze(mazeName); + Logger.Log(LogLevel.Information, "Entering maze '{MazeName}'", maze.Name); + PossibleActionsAndCurrentScore result = await MazeClient.EnterMaze(maze.Name); Stack directions = new Stack(); int collected = 0; do { - //await Task.Delay(500); - if (result.PossibleMoveActions.All(m => m.HasBeenVisited)) { - //LogConsole.WriteLine("All adjacent tiles have been visited! Going back."); + Logger.Log(LogLevel.Debug, "All adjacent tiles have been visited! Going back."); Direction direction = directions.Pop(); switch (direction) @@ -46,20 +47,20 @@ namespace Bobo.System.Maze.Bot } - //LogConsole.WriteLine($"Moving {direction}, I have been here."); + Logger.Log(LogLevel.Debug, "Moving {Direction}, I have been here.", direction); - result = await mazeClient.Move(direction); + result = await MazeClient.Move(direction); } else { MoveAction[] notVisited = result.PossibleMoveActions.Where(m => !m.HasBeenVisited).ToArray(); - //LogConsole.WriteLine($"{string.Join(", ", notVisited.Select(m => m.Direction.ToString()))} have not been visited, selecting next move."); + Logger.Log(LogLevel.Debug, $"{string.Join(", ", notVisited.Select(m => m.Direction.ToString()))} have not been visited, selecting next move."); int selected = random.Next(notVisited.Length - 1); MoveAction moveAction = notVisited[selected]; - //LogConsole.WriteLine($"Moving {moveAction.Direction}, I have {(!moveAction.HasBeenVisited ? "not" : string.Empty)} been here."); + Logger.Log(LogLevel.Debug, $"Moving {moveAction.Direction}, I have {(!moveAction.HasBeenVisited ? "not" : string.Empty)} been here."); - result = await mazeClient.Move(moveAction.Direction); + result = await MazeClient.Move(moveAction.Direction); directions.Push(moveAction.Direction); } @@ -67,17 +68,17 @@ namespace Bobo.System.Maze.Bot if (result.CanCollectScoreHere && result.CurrentScoreInHand > 0) { collected += result.CurrentScoreInHand; - await mazeClient.CollectScore(); + await MazeClient.CollectScore(); } - //LogConsole.WriteLine($"New tile has {(!result.CanExitMazeHere ? "no" : string.Empty)} exit."); + Logger.Log(LogLevel.Debug, $"New tile has {(!result.CanExitMazeHere ? "no" : string.Empty)} exit."); } while (!result.CanExitMazeHere); - await mazeClient.ExitMaze(); + await MazeClient.ExitMaze(); - LogConsole.WriteLine($"Collected {collected}!"); - LogConsole.WriteLine($"Exited maze {mazeName}!"); + Logger.Log(LogLevel.Information, "Collected {Collected}!", collected); + Logger.Log(LogLevel.Information, "Exited maze {MazeName}!", maze.Name); return collected; } diff --git a/Bobo.Systems.Maze.Console/Bobo.System.Maze.Console.csproj b/Bobo.System.Maze.Console/Bobo.System.Maze.Console.csproj similarity index 100% rename from Bobo.Systems.Maze.Console/Bobo.System.Maze.Console.csproj rename to Bobo.System.Maze.Console/Bobo.System.Maze.Console.csproj diff --git a/Bobo.Systems.Maze.Console/Program.cs b/Bobo.System.Maze.Console/Program.cs similarity index 94% rename from Bobo.Systems.Maze.Console/Program.cs rename to Bobo.System.Maze.Console/Program.cs index ef36620..34cbc92 100644 --- a/Bobo.Systems.Maze.Console/Program.cs +++ b/Bobo.System.Maze.Console/Program.cs @@ -1,5 +1,6 @@ // See https://aka.ms/new-console-template for more information using Bobo.System.Maze.Bot; +using Bobo.System.Maze.Bot.Interface; using HightechICT.Amazeing.Client.Rest; using Microsoft.Extensions.Logging; using Serilog; @@ -40,10 +41,10 @@ if (!registered) logger.Log(LogLevel.Information, $"Player '{username}' registered", username); logger.Log(LogLevel.Information, $"Starting SimplerBot"); - +BaseBot bot = new SimplerBot(mazeClient, logger); foreach (MazeInfo maze in mazes) { - int collected = await SimpleBot.Run(maze, mazeClient, logger); + int collected = await bot.Run(maze); logger.Log(LogLevel.Information, $"Collected {collected}/{maze.PotentialReward}", collected, maze.PotentialReward); } diff --git a/Bobo.Systems.Maze.sln b/Bobo.System.Maze.sln similarity index 81% rename from Bobo.Systems.Maze.sln rename to Bobo.System.Maze.sln index 98a4501..1c9e05b 100644 --- a/Bobo.Systems.Maze.sln +++ b/Bobo.System.Maze.sln @@ -3,10 +3,15 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.4.33103.184 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bobo.System.Maze.Console", "Bobo.Systems.Maze.Console\Bobo.System.Maze.Console.csproj", "{8E397C0A-34CF-4A55-94B5-889CBE8BDD1F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bobo.System.Maze.Console", "Bobo.System.Maze.Console\Bobo.System.Maze.Console.csproj", "{8E397C0A-34CF-4A55-94B5-889CBE8BDD1F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bobo.System.Maze.Bot", "Bobo.System.Maze.Bot\Bobo.System.Maze.Bot.csproj", "{754FC8DB-342D-4A5E-8193-E665D6F0DE02}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution Files", "{A0604FAF-75B5-497B-9639-EE340A1509F2}" + ProjectSection(SolutionItems) = preProject + readme.md = readme.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..8fea0e7 --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ +# Hightech ICT Maze runner/bot + +## Bots + +The bot solutions can be found here (./Bobo.System.Maze.Bot) +Currently there are 2 working bots