Created simpler bot using a stack collection
This commit is contained in:
parent
88bc7b9216
commit
5d7aa8a6d9
47
Bobo.Systems.Maze.Console/Bot/BumpBot.cs
Normal file
47
Bobo.Systems.Maze.Console/Bot/BumpBot.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using HightechICT.Amazeing.Client.Rest;
|
||||
using LogConsole = System.Console;
|
||||
|
||||
namespace Bobo.System.Maze.Console.Bot
|
||||
{
|
||||
internal class BumpBot
|
||||
{
|
||||
internal 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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
169
Bobo.Systems.Maze.Console/Bot/SimpleBot.cs
Normal file
169
Bobo.Systems.Maze.Console/Bot/SimpleBot.cs
Normal file
@ -0,0 +1,169 @@
|
||||
using Bobo.Systems.Maze.Console.Model;
|
||||
using HightechICT.Amazeing.Client.Rest;
|
||||
using System.Collections.ObjectModel;
|
||||
using LogConsole = System.Console;
|
||||
|
||||
|
||||
namespace Bobo.System.Maze.Console.Bot
|
||||
{
|
||||
internal class SimpleBot
|
||||
{
|
||||
private Collection<MazeTile> Maze = new();
|
||||
|
||||
internal MazeTile CurrentTile { get; set; } = new();
|
||||
|
||||
internal async Task Run(string mazeName, AmazeingClient mazeClient)
|
||||
{
|
||||
if (mazeClient == null)
|
||||
throw new ArgumentException(nameof(mazeClient));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(mazeName))
|
||||
throw new ArgumentException(nameof(mazeName));
|
||||
|
||||
Random random = new Random();
|
||||
LogConsole.WriteLine($"Entering maze '{mazeName}'");
|
||||
MazeTile result = new();
|
||||
CurrentTile = (await mazeClient.EnterMaze(mazeName)).ToMazeTile();
|
||||
Maze.Add(CurrentTile);
|
||||
foreach (MazeTile item in CurrentTile.PossibleMoveActions.Select(move => move.ToMazeTile(CurrentTile)))
|
||||
{
|
||||
AddOrUpdateMaze(item);
|
||||
}
|
||||
|
||||
RenderMaze();
|
||||
|
||||
do
|
||||
{
|
||||
await Task.Delay(100);
|
||||
LogConsole.Clear();
|
||||
// select a way to go
|
||||
MoveAction[] moves = CurrentTile.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))
|
||||
.ToMazeTile()
|
||||
.SetLocation(CurrentTile, moveAction.Direction);
|
||||
|
||||
CurrentTile = result;
|
||||
|
||||
AddOrUpdateMaze(result);
|
||||
|
||||
foreach (MazeTile item in result.PossibleMoveActions.Select(move => move.ToMazeTile(result)))
|
||||
{
|
||||
AddOrUpdateMaze(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogConsole.WriteLine($"New tile has {(!CurrentTile.CanExitMazeHere ? "no" : string.Empty)} exit.");
|
||||
|
||||
RenderMaze();
|
||||
|
||||
LogConsole.ReadKey(true);
|
||||
|
||||
} while (!CurrentTile.CanExitMazeHere);
|
||||
|
||||
await mazeClient.ExitMaze();
|
||||
|
||||
LogConsole.WriteLine($"Exited the maze!");
|
||||
}
|
||||
|
||||
internal void AddOrUpdateMaze(MazeTile tile)
|
||||
{
|
||||
string tileLocation = $"[{tile.X},{tile.Y}]";
|
||||
// fetch the tile from the collection, if there is one
|
||||
MazeTile? inCollection = Maze.SingleOrDefault(listTile => listTile.X == tile.X && listTile.Y == tile.Y);
|
||||
|
||||
|
||||
if (inCollection != null)
|
||||
{
|
||||
if (CurrentTile.X == inCollection.X && CurrentTile.Y == tile.Y)
|
||||
{
|
||||
LogConsole.WriteLine($"{tileLocation} updating tile standing tile");
|
||||
Maze.Remove(inCollection);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogConsole.WriteLine($"{tileLocation} tile exists and we are not on it, skiping tile.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogConsole.WriteLine($"{tileLocation} not found in collection.");
|
||||
}
|
||||
|
||||
LogConsole.WriteLine($"Adding {tileLocation} to Maze collecion");
|
||||
|
||||
Maze.Add(tile);
|
||||
}
|
||||
|
||||
internal void RenderMaze()
|
||||
{
|
||||
int minY = Maze.Min(t => t.Y), maxY = Maze.Max(t => t.Y);
|
||||
|
||||
int totalY = Math.Abs(maxY - minY);
|
||||
|
||||
// render the header
|
||||
// render the left prefix
|
||||
LogConsole.Write(" " + string.Join("", Enumerable.Range(minY, totalY).Select(t => PadBoth(t.ToString(), 3))));
|
||||
LogConsole.WriteLine();
|
||||
|
||||
// render the row of X tiles + the paths between if any
|
||||
|
||||
|
||||
|
||||
|
||||
foreach (MazeTile tile in Maze.OrderBy(t => t.X).ThenBy(t => t.Y))
|
||||
{
|
||||
LogConsole.WriteLine($"[{tile.X},{tile.Y}] - visited: {tile.HasBeenVisited}; paths: {(tile.PossibleMoveActions != null ? string.Join(',', tile.PossibleMoveActions.Select(d => d.Direction.ToString())) : "unknown")}");
|
||||
}
|
||||
}
|
||||
|
||||
internal string PadBoth(string source, int length)
|
||||
{
|
||||
int spaces = length - source.Length;
|
||||
int padLeft = spaces / 2 + source.Length;
|
||||
return source.PadLeft(padLeft).PadRight(length);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Converter
|
||||
{
|
||||
public static MazeTile ToMazeTile(this PossibleActionsAndCurrentScore possibleActionsAndCurrentScore)
|
||||
{
|
||||
MazeTile tile = new();
|
||||
tile.PossibleMoveActions = possibleActionsAndCurrentScore.PossibleMoveActions;
|
||||
tile.CanCollectScoreHere = possibleActionsAndCurrentScore.CanCollectScoreHere;
|
||||
tile.CanExitMazeHere = possibleActionsAndCurrentScore.CanExitMazeHere;
|
||||
tile.CurrentScoreInHand = possibleActionsAndCurrentScore.CurrentScoreInHand;
|
||||
tile.CurrentScoreInBag = possibleActionsAndCurrentScore.CurrentScoreInBag;
|
||||
tile.HasBeenVisited = true;
|
||||
return tile;
|
||||
}
|
||||
|
||||
public static MazeTile ToMazeTile(this MoveAction moveAction, MazeTile source)
|
||||
{
|
||||
MazeTile tile = new MazeTile();
|
||||
tile.HasBeenVisited = moveAction.HasBeenVisited;
|
||||
tile.SetLocation(source, moveAction.Direction);
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
85
Bobo.Systems.Maze.Console/Bot/SimplerBot.cs
Normal file
85
Bobo.Systems.Maze.Console/Bot/SimplerBot.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using HightechICT.Amazeing.Client.Rest;
|
||||
using LogConsole = System.Console;
|
||||
|
||||
|
||||
namespace Bobo.System.Maze.Console.Bot
|
||||
{
|
||||
internal class SimplerBot
|
||||
{
|
||||
internal static async Task<int> Run(string mazeName, AmazeingClient mazeClient)
|
||||
{
|
||||
if (mazeClient == null)
|
||||
throw new ArgumentException(nameof(mazeClient));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(mazeName))
|
||||
throw new ArgumentException(nameof(mazeName));
|
||||
|
||||
Random random = new Random();
|
||||
LogConsole.WriteLine($"Entering maze '{mazeName}'");
|
||||
PossibleActionsAndCurrentScore result = await mazeClient.EnterMaze(mazeName);
|
||||
Stack<Direction> directions = new Stack<Direction>();
|
||||
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.");
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
//LogConsole.WriteLine($"Moving {direction}, I have been here.");
|
||||
|
||||
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.");
|
||||
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.");
|
||||
|
||||
result = await mazeClient.Move(moveAction.Direction);
|
||||
|
||||
directions.Push(moveAction.Direction);
|
||||
}
|
||||
|
||||
if (result.CanCollectScoreHere && result.CurrentScoreInHand > 0)
|
||||
{
|
||||
collected += result.CurrentScoreInHand;
|
||||
await mazeClient.CollectScore();
|
||||
}
|
||||
|
||||
//LogConsole.WriteLine($"New tile has {(!result.CanExitMazeHere ? "no" : string.Empty)} exit.");
|
||||
|
||||
} while (!result.CanExitMazeHere);
|
||||
|
||||
await mazeClient.ExitMaze();
|
||||
|
||||
LogConsole.WriteLine($"Collected {collected}!");
|
||||
LogConsole.WriteLine($"Exited maze {mazeName}!");
|
||||
|
||||
return collected;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Bobo.Systems.Maze.Console/Model/MazeTile.cs
Normal file
38
Bobo.Systems.Maze.Console/Model/MazeTile.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using HightechICT.Amazeing.Client.Rest;
|
||||
|
||||
namespace Bobo.Systems.Maze.Console.Model
|
||||
{
|
||||
public class MazeTile : PossibleActionsAndCurrentScore
|
||||
{
|
||||
public int X { get; set; } = 0;
|
||||
public int Y { get; set; } = 0;
|
||||
public bool HasBeenVisited { get; set; }
|
||||
|
||||
public MazeTile SetLocation(MazeTile source, Direction direction)
|
||||
{
|
||||
X = source.X;
|
||||
Y = source.Y;
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
case Direction.Up:
|
||||
X++;
|
||||
break;
|
||||
|
||||
case Direction.Down:
|
||||
X--;
|
||||
break;
|
||||
|
||||
case Direction.Right:
|
||||
Y++;
|
||||
break;
|
||||
|
||||
case Direction.Left:
|
||||
Y--;
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,14 +16,7 @@ httpClient.DefaultRequestHeaders.Add("Authorization", apiAuthorization);
|
||||
|
||||
AmazeingClient mazeClient = new AmazeingClient(baseUrl, httpClient);
|
||||
|
||||
|
||||
ICollection<MazeInfo> mazeInfos = await mazeClient.AllMazes();
|
||||
|
||||
foreach(MazeInfo info in mazeInfos)
|
||||
{
|
||||
Console.WriteLine($"Name: {info.Name}, Tiles: {info.TotalTiles}");
|
||||
}
|
||||
|
||||
ICollection<MazeInfo> mazes = await mazeClient.AllMazes();
|
||||
|
||||
bool registered = await RegisterPlayer(username, true);
|
||||
|
||||
@ -35,9 +28,13 @@ if (!registered)
|
||||
|
||||
Console.WriteLine($"Player '{username}' registered");
|
||||
|
||||
Console.WriteLine($"Starting SimpleBot");
|
||||
|
||||
await SimpleBot.Run(mazeName, mazeClient);
|
||||
Console.WriteLine($"Starting SimplerBot");
|
||||
foreach (MazeInfo maze in mazes)
|
||||
{
|
||||
int collected = await SimplerBot.Run(maze.Name, mazeClient);
|
||||
Console.WriteLine($"Collected {collected}/{maze.PotentialReward}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
async Task<bool> RegisterPlayer(string username, bool reset = false)
|
||||
{
|
||||
@ -65,7 +62,6 @@ async Task<bool> RegisterPlayer(string username, bool reset = false)
|
||||
{
|
||||
// forget the player.
|
||||
await mazeClient.ForgetPlayer();
|
||||
return true;
|
||||
}
|
||||
catch (ApiException apiEx)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user