Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- namespace MonkeyIslandAdventure;
- // Represents a coordinate in the 3D treasure map.
- public readonly record struct IslandCoordinate(int X, int Y, int Z);
- // Base class for all pirate commands.
- public abstract record PirateCommand
- {
- public abstract void Execute(Guybrush guybrush);
- }
- // Hoist instruction class.
- public sealed record HoistInstruction(Func<IslandCoordinate, int> ValueProvider) : PirateCommand
- {
- public override void Execute(Guybrush guybrush)
- {
- int piecesOfEight = ValueProvider(guybrush.CurrentLocation);
- guybrush.LootSack.Push(piecesOfEight);
- guybrush.CompassPointer++;
- }
- }
- // Plunder instruction class.
- public sealed record PlunderInstruction() : PirateCommand
- {
- public override void Execute(Guybrush guybrush)
- {
- if (guybrush.LootSack.Count < 2)
- throw new InvalidOperationException("Ye don't have enough booty for plunderin'!");
- int val1 = guybrush.LootSack.Pop();
- int val2 = guybrush.LootSack.Pop();
- guybrush.LootSack.Push(val1 + val2);
- guybrush.CompassPointer++;
- }
- }
- // SetSail instruction class.
- public sealed record SetSailInstruction(int Offset) : PirateCommand
- {
- public override void Execute(Guybrush guybrush)
- {
- if (guybrush.LootSack.Count < 1)
- throw new InvalidOperationException("Ye can't set sail without any loot!");
- int piecesOfEight = guybrush.LootSack.Pop();
- if (piecesOfEight >= 0)
- guybrush.CompassPointer += Offset;
- guybrush.CompassPointer++;
- }
- }
- // Dock instruction class.
- public sealed record DockInstruction() : PirateCommand
- {
- public override void Execute(Guybrush guybrush)
- {
- if (guybrush.LootSack.Count < 1)
- throw new InvalidOperationException("No booty to dock with!");
- guybrush.BootyValue = guybrush.LootSack.Peek();
- guybrush.QuestComplete = true;
- }
- }
- // Guybrush class that represents our hero on his adventure.
- public class Guybrush
- {
- public Stack<int> LootSack { get; } = new();
- public int CompassPointer { get; set; }
- public bool QuestComplete { get; set; }
- public int BootyValue { get; set; }
- public IslandCoordinate CurrentLocation { get; }
- private readonly List<PirateCommand> _pirateCommands;
- public Guybrush(List<PirateCommand> pirateCommands, IslandCoordinate location)
- {
- _pirateCommands = pirateCommands ?? throw new ArgumentNullException(nameof(pirateCommands));
- CurrentLocation = location;
- }
- public int EmbarkOnQuest()
- {
- while (!QuestComplete && CompassPointer >= 0 && CompassPointer < _pirateCommands.Count)
- {
- PirateCommand command = _pirateCommands[CompassPointer];
- command.Execute(this);
- }
- if (!QuestComplete)
- throw new InvalidOperationException("Guybrush didn't find the treasure!");
- return BootyValue;
- }
- }
- // Reads the treasure map and interprets the pirate commands.
- public static class MapReader
- {
- public static List<PirateCommand> ReadPirateCommands(string[] lines)
- {
- var pirateCommands = new List<PirateCommand>();
- foreach (string line in lines)
- {
- if (string.IsNullOrWhiteSpace(line))
- continue;
- PirateCommand command = ParseCommand(line);
- pirateCommands.Add(command);
- }
- return pirateCommands;
- }
- private static PirateCommand ParseCommand(string line)
- {
- string[] parts = line.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
- if (parts.Length == 0)
- throw new InvalidOperationException("Empty pirate command!");
- string command = parts[0].ToLowerInvariant();
- string[] args = parts.Length > 1 ? parts[1..] : Array.Empty<string>();
- return command switch
- {
- "push" => CreateHoistInstruction(args),
- "add" => new PlunderInstruction(),
- "jmpos" => CreateSetSailInstruction(args),
- "ret" => new DockInstruction(),
- _ => throw new InvalidOperationException($"Unknown pirate command: {line}")
- };
- }
- private static PirateCommand CreateHoistInstruction(string[] args)
- {
- if (args.Length != 1)
- throw new InvalidOperationException("Invalid hoist instruction.");
- string valueStr = args[0].ToLowerInvariant();
- Func<IslandCoordinate, int> valueProvider = valueStr switch
- {
- "x" => coord => coord.X,
- "y" => coord => coord.Y,
- "z" => coord => coord.Z,
- _ => int.TryParse(valueStr, out int intValue)
- ? _ => intValue
- : throw new InvalidOperationException($"Invalid hoist value: {valueStr}")
- };
- return new HoistInstruction(valueProvider);
- }
- private static PirateCommand CreateSetSailInstruction(string[] args)
- {
- if (args.Length != 1)
- throw new InvalidOperationException("Invalid setsail instruction.");
- if (!int.TryParse(args[0], out int offset))
- throw new InvalidOperationException($"Invalid setsail offset: {args[0]}");
- return new SetSailInstruction(offset);
- }
- }
- // Represents the treasure map (3D grid).
- public class TreasureMap
- {
- private readonly int[,,] _data;
- public int Width { get; }
- public int Height { get; }
- public int Depth { get; }
- public TreasureMap(int width, int height, int depth)
- {
- Width = width;
- Height = height;
- Depth = depth;
- _data = new int[width, height, depth];
- }
- public int this[int x, int y, int z]
- {
- get => _data[x, y, z];
- set => _data[x, y, z] = value;
- }
- public IEnumerable<IslandCoordinate> GetIslands()
- {
- for (int x = 0; x < Width; x++)
- for (int y = 0; y < Height; y++)
- for (int z = 0; z < Depth; z++)
- yield return new IslandCoordinate(x, y, z);
- }
- }
- // Counts the number of ghost ships (clouds) on the map.
- public static class GhostShipCounter
- {
- private static readonly (int dx, int dy, int dz)[] WindDirections = new[]
- {
- (-1, 0, 0), (1, 0, 0),
- (0, -1, 0), (0, 1, 0),
- (0, 0, -1), (0, 0, 1)
- };
- public static int CountGhostShips(TreasureMap map)
- {
- int ghostShipCount = 0;
- var visited = new bool[map.Width, map.Height, map.Depth];
- foreach (var coord in map.GetIslands())
- {
- if (map[coord.X, coord.Y, coord.Z] > 0 && !visited[coord.X, coord.Y, coord.Z])
- {
- SailTheSevenSeas(map, visited, coord);
- ghostShipCount++;
- }
- }
- return ghostShipCount;
- }
- private static void SailTheSevenSeas(TreasureMap map, bool[,,] visited, IslandCoordinate startCoord)
- {
- var stack = new Stack<IslandCoordinate>();
- stack.Push(startCoord);
- visited[startCoord.X, startCoord.Y, startCoord.Z] = true;
- while (stack.Count > 0)
- {
- var coord = stack.Pop();
- foreach (var (dx, dy, dz) in WindDirections)
- {
- int nx = coord.X + dx;
- int ny = coord.Y + dy;
- int nz = coord.Z + dz;
- if (nx >= 0 && nx < map.Width &&
- ny >= 0 && ny < map.Height &&
- nz >= 0 && nz < map.Depth &&
- map[nx, ny, nz] > 0 &&
- !visited[nx, ny, nz])
- {
- visited[nx, ny, nz] = true;
- stack.Push(new IslandCoordinate(nx, ny, nz));
- }
- }
- }
- }
- }
- // The ScummBar is where our adventure begins!
- public class ScummBar
- {
- private const int IslandSize = 30;
- private static List<PirateCommand> _pirateCommands;
- public static void Main(string[] args)
- {
- try
- {
- // Guybrush enters the Scumm Bar and finds a mysterious map.
- Console.WriteLine("Ahoy! Welcome to Guybrush Threepwood's grand adventure!");
- // Read the pirate commands from the treasure map.
- string[] lines = File.ReadAllLines("pirate_commands.txt");
- _pirateCommands = MapReader.ReadPirateCommands(lines);
- // Chart the seas and find the treasure.
- TreasureMap treasureMap = new(IslandSize, IslandSize, IslandSize);
- long totalTreasure = ChartTheSeas(treasureMap);
- Console.WriteLine($"Total treasure collected: {totalTreasure} pieces of eight");
- // Count the number of ghost ships.
- int ghostShipCount = GhostShipCounter.CountGhostShips(treasureMap);
- Console.WriteLine($"Number of ghost ships spotted: {ghostShipCount}");
- Console.WriteLine("Ye've completed the quest! Time to celebrate at the Scumm Bar!");
- }
- catch (Exception ex)
- {
- Console.Error.WriteLine($"Curse ye scurvy code! Error: {ex.Message}");
- }
- }
- private static long ChartTheSeas(TreasureMap map)
- {
- long totalTreasure = 0;
- foreach (var coord in map.GetIslands())
- {
- int booty = EmbarkOnQuest(coord);
- map[coord.X, coord.Y, coord.Z] = booty;
- totalTreasure += booty;
- }
- return totalTreasure;
- }
- private static int EmbarkOnQuest(IslandCoordinate location)
- {
- var guybrush = new Guybrush(_pirateCommands, location);
- return guybrush.EmbarkOnQuest();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement