summaryrefslogtreecommitdiff
path: root/MorgSimulator/Framework/Entity.cs
blob: d415fddf2e6329082719f3218c5d005facad31d3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using System.Collections.Generic;

namespace MorgSimulator.Framework
{
    public abstract class Entity(int id, (int x, int y) location, (int x, int y) direction)
    {
        public int Id { get; set; } = id;
        public string Type { get; 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; set; } = null!;
        public IFeedingStrategy FeedingStrategy { get; set; } = null!;
        public List<string> PreyTypes { get; set; } = [];
#nullable enable
        public Entity? Prey { get; set; }
#nullable disable

        private readonly List<Entity> _observers = [];

        public void Attach(Entity observer)
        {
            if (!_observers.Contains(observer))
                _observers.Add(observer);
        }

        public void Detach(Entity observer)
        {
            _observers.Remove(observer);
        }

        public void Notify()
        {
            foreach (var observer in _observers)
                observer.Update(this);
        }

        public virtual void Update(Entity 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);
        }
    }
}