summaryrefslogtreecommitdiff
path: root/MorgSimulator/Framework/Simulator.cs
blob: 6e8c694ad2fa5572729270778b9f59f62b67a7e9 (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
using System.Collections.Generic;

namespace MorgSimulator.Framework
{
    public abstract class Simulator<T> where T : Entity
    {
        protected readonly List<T> _entities = [];
        protected const double FEEDING_DISTANCE = 1.0;

        public void AddEntity(T entity)
        {
            _entities.Add(entity);
        }

        public IEnumerable<T> GetAllEntities()
        {
            return _entities;
        }

        public IEntityIterator<T> CreateIterator()
        {
            return new EntityIterator<T>(_entities);
        }

        public void Run(int runTime)
        {
            for (int timeStep = 0; timeStep < runTime; timeStep++)
                ProcessTimeStep();
        }

        protected virtual void ProcessTimeStep()
        {
            foreach (var entity in _entities)
                if (entity.IsAlive)
                {
                    FindPreyIfNeeded(entity);
                    entity.Move();
                    CheckAndFeed(entity);
                }
        }

        protected virtual void FindPreyIfNeeded(T entity)
        {
            if (entity.Prey == null || !entity.Prey.IsAlive)
            {
                var nearestPrey = FindNearestPrey(entity);

                if (nearestPrey != null)
                {
                    nearestPrey.Attach(entity);

                    entity.Prey = nearestPrey as T;
                    entity.Direction = entity.CalculateDirectionToTarget(nearestPrey.Location);
                }
            }
        }

        protected virtual void CheckAndFeed(T entity)
        {
            if (entity.Prey != null && entity.Prey.IsAlive &&
                entity.DistanceTo(entity.Prey.Location) <= FEEDING_DISTANCE)
                entity.Feed();
        }

#nullable enable
        protected abstract Entity? FindNearestPrey(T predator);
#nullable disable
    }
}