summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-10-16 20:23:12 -0700
committerFuwn <[email protected]>2025-10-16 20:23:12 -0700
commitc9d655807d0046be1fa2cd19991354b703c55c87 (patch)
treeac14221c639baf208c01cc11ee01649d9eef05b7
downloadcst276-c9d655807d0046be1fa2cd19991354b703c55c87.tar.xz
cst276-c9d655807d0046be1fa2cd19991354b703c55c87.zip
feat: Implement Assignment 1 functionality
-rw-r--r--.gitignore10
-rw-r--r--MorgSimulator.csproj10
-rw-r--r--MorgSimulator/Dish.cs42
-rw-r--r--MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs12
-rw-r--r--MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs12
-rw-r--r--MorgSimulator/IFeedingStrategy.cs7
-rw-r--r--MorgSimulator/IMovementStrategy.cs7
-rw-r--r--MorgSimulator/Morg.cs87
-rw-r--r--MorgSimulator/MovementStrategy/MovementStrategyOozes.cs12
-rw-r--r--MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs12
-rw-r--r--MorgSimulator/Program.cs36
-rw-r--r--MorgSimulator/Type/TypeAMorg.cs16
-rw-r--r--MorgSimulator/Type/TypeBMorg.cs15
-rw-r--r--MorgSimulator/Type/TypeCMorg.cs16
-rw-r--r--justfile15
15 files changed, 309 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..263f35f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+# .NET
+obj
+bin
+docs
+
+# Visual Studio Code
+.vscode
+
+# macOS
+.DS_Store
diff --git a/MorgSimulator.csproj b/MorgSimulator.csproj
new file mode 100644
index 0000000..017f6f8
--- /dev/null
+++ b/MorgSimulator.csproj
@@ -0,0 +1,10 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net9.0</TargetFramework>
+ <ImplicitUsings>false</ImplicitUsings>
+ <Nullable>warnings</Nullable>
+ </PropertyGroup>
+
+</Project>
diff --git a/MorgSimulator/Dish.cs b/MorgSimulator/Dish.cs
new file mode 100644
index 0000000..d81fc8a
--- /dev/null
+++ b/MorgSimulator/Dish.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MorgSimulator
+{
+ public class Dish
+ {
+ private readonly List<Morg> _morgs = [];
+
+ public void AddMorg(Morg morg)
+ {
+ _morgs.Add(morg);
+ }
+
+ public List<Morg> GetAllMorgs()
+ {
+ return [.. _morgs];
+ }
+
+#nullable enable
+ public Morg? FindNearestPrey(Morg predator)
+ {
+ Morg? nearestPrey = null;
+ double nearestDistance = double.MaxValue;
+
+ foreach (var potentialPrey in _morgs.Where(m => m.IsAlive && m != predator))
+ if (predator.CanEat(potentialPrey.Type))
+ {
+ double distance = predator.DistanceTo(potentialPrey.Location);
+
+ if (distance < nearestDistance)
+ {
+ nearestDistance = distance;
+ nearestPrey = potentialPrey;
+ }
+ }
+
+ return nearestPrey;
+ }
+#nullable disable
+ }
+} \ No newline at end of file
diff --git a/MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs b/MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs
new file mode 100644
index 0000000..9e0f9a0
--- /dev/null
+++ b/MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs
@@ -0,0 +1,12 @@
+namespace MorgSimulator
+{
+ public class FeedingStrategyAbsorbs : IFeedingStrategy
+ {
+ public void Feed(Morg predator, Morg prey)
+ {
+ System.Console.WriteLine($"Morg {predator.Id} Absorbs Morg {prey.Id} at ({prey.Location.x},{prey.Location.y})");
+
+ prey.IsAlive = false;
+ }
+ }
+}
diff --git a/MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs b/MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs
new file mode 100644
index 0000000..d35227c
--- /dev/null
+++ b/MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs
@@ -0,0 +1,12 @@
+namespace MorgSimulator
+{
+ public class FeedingStrategyEnvelops : IFeedingStrategy
+ {
+ public void Feed(Morg predator, Morg prey)
+ {
+ System.Console.WriteLine($"Morg {predator.Id} Envelops Morg {prey.Id} at ({prey.Location.x},{prey.Location.y})");
+
+ prey.IsAlive = false;
+ }
+ }
+}
diff --git a/MorgSimulator/IFeedingStrategy.cs b/MorgSimulator/IFeedingStrategy.cs
new file mode 100644
index 0000000..b0344ea
--- /dev/null
+++ b/MorgSimulator/IFeedingStrategy.cs
@@ -0,0 +1,7 @@
+namespace MorgSimulator
+{
+ public interface IFeedingStrategy
+ {
+ void Feed(Morg predator, Morg prey);
+ }
+}
diff --git a/MorgSimulator/IMovementStrategy.cs b/MorgSimulator/IMovementStrategy.cs
new file mode 100644
index 0000000..2b073e1
--- /dev/null
+++ b/MorgSimulator/IMovementStrategy.cs
@@ -0,0 +1,7 @@
+namespace MorgSimulator
+{
+ public interface IMovementStrategy
+ {
+ void Move(Morg morg, (int x, int y) newLocation);
+ }
+}
diff --git a/MorgSimulator/Morg.cs b/MorgSimulator/Morg.cs
new file mode 100644
index 0000000..62048bf
--- /dev/null
+++ b/MorgSimulator/Morg.cs
@@ -0,0 +1,87 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MorgSimulator
+{
+ public abstract class Morg(int id, (int x, int y) location, (int x, int y) direction)
+ {
+ public int Id { get; set; } = id;
+ public string Type { get; protected set; } = string.Empty;
+ public (int x, int y) Location { get; set; } = location;
+ public (int x, int y) Direction { get; set; } = direction;
+ public bool IsAlive { get; set; } = true;
+ public IMovementStrategy MovementStrategy { get; protected set; } = null!;
+ public IFeedingStrategy FeedingStrategy { get; protected set; } = null!;
+ public List<string> PreyTypes { get; protected set; } = new List<string>();
+#nullable enable
+ public Morg? Prey { get; set; }
+#nullable disable
+
+ private readonly List<Morg> _observers = [];
+
+ public void Attach(Morg observer)
+ {
+ if (!_observers.Contains(observer))
+ _observers.Add(observer);
+ }
+
+ public void Detach(Morg observer)
+ {
+ _observers.Remove(observer);
+ }
+
+ public void Notify()
+ {
+ foreach (var observer in _observers.ToList())
+ observer.Update(this);
+ }
+
+ public virtual void Update(Morg subject)
+ {
+ Direction = CalculateDirectionToTarget(subject.Location);
+ }
+
+ public virtual void Move()
+ {
+ if (!IsAlive) return;
+
+ var newLocation = (Location.x + Direction.x, Location.y + Direction.y);
+
+ MovementStrategy.Move(this, newLocation);
+ Notify();
+ }
+
+ public virtual void Feed()
+ {
+ if (!IsAlive || Prey == null || !Prey.IsAlive) return;
+
+ FeedingStrategy.Feed(this, Prey);
+
+ Prey = null;
+ }
+
+ public bool CanEat(string targetType)
+ {
+ return PreyTypes.Contains(targetType);
+ }
+
+ public (int x, int y) CalculateDirectionToTarget((int x, int y) target)
+ {
+ int deltaX = target.x - Location.x;
+ int deltaY = target.y - Location.y;
+ int directionX = deltaX > 0 ? 1 : (deltaX < 0 ? -1 : 0);
+ int directionY = deltaY > 0 ? 1 : (deltaY < 0 ? -1 : 0);
+
+ return (directionX, directionY);
+ }
+
+ public double DistanceTo((int x, int y) target)
+ {
+ int deltaX = target.x - Location.x;
+ int deltaY = target.y - Location.y;
+
+ return System.Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/MorgSimulator/MovementStrategy/MovementStrategyOozes.cs b/MorgSimulator/MovementStrategy/MovementStrategyOozes.cs
new file mode 100644
index 0000000..217d175
--- /dev/null
+++ b/MorgSimulator/MovementStrategy/MovementStrategyOozes.cs
@@ -0,0 +1,12 @@
+namespace MorgSimulator
+{
+ public class MovementStrategyOozes : IMovementStrategy
+ {
+ public void Move(Morg morg, (int x, int y) newLocation)
+ {
+ System.Console.WriteLine($"Morg {morg.Id} Oozes from ({morg.Location.x},{morg.Location.y}) to ({newLocation.x},{newLocation.y})");
+
+ morg.Location = newLocation;
+ }
+ }
+}
diff --git a/MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs b/MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs
new file mode 100644
index 0000000..efdd3ef
--- /dev/null
+++ b/MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs
@@ -0,0 +1,12 @@
+namespace MorgSimulator
+{
+ public class MovementStrategyPaddles : IMovementStrategy
+ {
+ public void Move(Morg morg, (int x, int y) newLocation)
+ {
+ System.Console.WriteLine($"Morg {morg.Id} Paddles from ({morg.Location.x},{morg.Location.y}) to ({newLocation.x},{newLocation.y})");
+
+ morg.Location = newLocation;
+ }
+ }
+}
diff --git a/MorgSimulator/Program.cs b/MorgSimulator/Program.cs
new file mode 100644
index 0000000..bf15776
--- /dev/null
+++ b/MorgSimulator/Program.cs
@@ -0,0 +1,36 @@
+using MorgSimulator;
+
+var dish = new Dish();
+
+dish.AddMorg(new TypeAMorg(1, (0, 0), (1, 0)));
+dish.AddMorg(new TypeAMorg(2, (10, 10), (-1, -1)));
+dish.AddMorg(new TypeBMorg(3, (5, 5), (0, 1)));
+dish.AddMorg(new TypeBMorg(4, (15, 0), (-1, 0)));
+dish.AddMorg(new TypeCMorg(5, (8, 8), (0, -1)));
+dish.AddMorg(new TypeCMorg(6, (20, 5), (-1, 1)));
+
+const int RUN_TIME = 15;
+
+for (int timeStep = 0; timeStep < RUN_TIME; timeStep++)
+ foreach (var morg in dish.GetAllMorgs())
+ if (morg.IsAlive)
+ {
+ if (morg.Prey == null || !morg.Prey.IsAlive)
+ {
+ var nearestPrey = dish.FindNearestPrey(morg);
+
+ if (nearestPrey != null)
+ {
+ nearestPrey.Attach(morg);
+
+ morg.Prey = nearestPrey;
+ morg.Direction = morg.CalculateDirectionToTarget(nearestPrey.Location);
+ }
+ }
+
+ morg.Move();
+ morg.Notify();
+
+ if (morg.Prey != null && morg.Prey.IsAlive && morg.DistanceTo(morg.Prey.Location) <= 1.0)
+ morg.Feed();
+ }
diff --git a/MorgSimulator/Type/TypeAMorg.cs b/MorgSimulator/Type/TypeAMorg.cs
new file mode 100644
index 0000000..376f054
--- /dev/null
+++ b/MorgSimulator/Type/TypeAMorg.cs
@@ -0,0 +1,16 @@
+namespace MorgSimulator
+{
+ public class TypeAMorg : Morg
+ {
+ public TypeAMorg(int id, (int x, int y) location, (int x, int y) direction)
+ : base(id, location, direction)
+ {
+ Type = "A";
+ MovementStrategy = new MovementStrategyPaddles();
+ FeedingStrategy = new FeedingStrategyAbsorbs();
+
+ PreyTypes.Add("B");
+ PreyTypes.Add("C");
+ }
+ }
+}
diff --git a/MorgSimulator/Type/TypeBMorg.cs b/MorgSimulator/Type/TypeBMorg.cs
new file mode 100644
index 0000000..5b235ed
--- /dev/null
+++ b/MorgSimulator/Type/TypeBMorg.cs
@@ -0,0 +1,15 @@
+namespace MorgSimulator
+{
+ public class TypeBMorg : Morg
+ {
+ public TypeBMorg(int id, (int x, int y) location, (int x, int y) direction)
+ : base(id, location, direction)
+ {
+ Type = "B";
+ MovementStrategy = new MovementStrategyOozes();
+ FeedingStrategy = new FeedingStrategyEnvelops();
+
+ PreyTypes.Add("A");
+ }
+ }
+}
diff --git a/MorgSimulator/Type/TypeCMorg.cs b/MorgSimulator/Type/TypeCMorg.cs
new file mode 100644
index 0000000..35577a1
--- /dev/null
+++ b/MorgSimulator/Type/TypeCMorg.cs
@@ -0,0 +1,16 @@
+namespace MorgSimulator
+{
+ public class TypeCMorg : Morg
+ {
+ public TypeCMorg(int id, (int x, int y) location, (int x, int y) direction)
+ : base(id, location, direction)
+ {
+ Type = "C";
+ MovementStrategy = new MovementStrategyPaddles();
+ FeedingStrategy = new FeedingStrategyEnvelops();
+
+ PreyTypes.Add("A");
+ PreyTypes.Add("B");
+ }
+ }
+}
diff --git a/justfile b/justfile
new file mode 100644
index 0000000..976d1b8
--- /dev/null
+++ b/justfile
@@ -0,0 +1,15 @@
+name := "MorgSimulator"
+
+alias fmt := format
+
+dotnet_execute command:
+ dotnet {{ command }} ./{{ name }}.csproj --verbosity diagnostic
+
+format:
+ just dotnet_execute format
+
+build:
+ just dotnet_execute build
+
+run:
+ just dotnet_execute run