text:
using Subterfuge.Remake.Core.Entities;
using Subterfuge.Remake.Core.Entities.Components;
using Subterfuge.Remake.Core.GameEvents.Base;
using Subterfuge.Remake.Core.GameEvents.Combat;
using Subterfuge.Remake.Core.Timing;
using PositionalGameEvent = Subterfuge.Remake.Core.GameEvents.Combat.PositionalGameEvent;

namespace Subterfuge.Remake.Core.GameEvents.SpecialistEvents
{
    public class SpecialistCapacityChangeEvent : PositionalGameEvent
    {
        private IEntity _expectedWinLocationToApply;
        private int _delta;

        public SpecialistCapacityChangeEvent(
            GameTick occursAt,
            IEntity expectedWinLocation,
            int delta
        ) : base(occursAt, Priority.SPECIALIST_CAPCITY_CHANGE, expectedWinLocation)
        {
            _expectedWinLocationToApply = expectedWinLocation;
            _delta = delta;
        }

        public override bool ForwardAction(TimeMachine timeMachine)
        {
            _expectedWinLocationToApply.GetComponent<SpecialistManager>().AlterCapacity(_delta);
            return true;
        }

        public override bool BackwardAction(TimeMachine timeMachine)
        {
            _expectedWinLocationToApply.GetComponent<SpecialistManager>().AlterCapacity(_delta * -1);
            return true;
        }

        public override bool WasEventSuccessful()
        {
            return true;
        }
    }
}


text:
using Subterfuge.Remake.Core.GameEvents.Base;
using Subterfuge.Remake.Core.GameEvents.Combat;
using Subterfuge.Remake.Core.Timing;
using PositionalGameEvent = Subterfuge.Remake.Core.GameEvents.Combat.PositionalGameEvent;

namespace Subterfuge.Remake.Core.GameEvents.SpecialistEvents
{
    public class NoOpGameEvent : GameEvent
    {
        public NoOpGameEvent(GameTick occursAt) : base(occursAt, Priority.COMBAT_RESOLVE)
        {
        }

        public override bool ForwardAction(TimeMachine timeMachine)
        {
            this.EventSuccess = true;
            return true;
        }

        public override bool BackwardAction(TimeMachine timeMachine)
        {
            return true;
        }

        public override string GetEventId()
        {
            return "NoOp";
        }

        public override bool Equals(object other)
        {
            NoOpGameEvent asEvent = other as NoOpGameEvent;
            if (other == null)
                return false;

            return Equals(asEvent?.OccursAt, OccursAt);
        }

        public override int GetHashCode()
        {
            return OccursAt.GetHashCode();
        }

        public override bool WasEventSuccessful()
        {
            return this.EventSuccess;
        }
    }
}

repo_name: Subterfuge-Revived/Remake-Core

repo_language: C#

mime_type: text/plain


text:
using System;
using System.Numerics;

namespace Subterfuge.Remake.Core.Topologies
{

	/// <summary>
	/// A Vector in a Rectangular Flat Torus (Rft) map. (x,y) is in
	/// (-map.width/2, map.width/2] x (-map.height/2, map.height/2]
	/// </summary>
	public class RftVector
	{
		/// <summary>
		/// The x-value of the RftVector. This is in the interval (-map.width/2, map.width/2].
		/// </summary>
		private float _x;

		public float X
		{
			get { return _x; }
			set
			{
				_x = (value % Map.Width + Map.Width) % Map.Width;
				if (_x > Map.Width / 2) _x -= Map.Width;
			}
		}

		/// <summary>
		/// The y value of the RftVector. This is in the interval (-map.height/2, map.height/2].
		/// </summary>
		private float _y;

		public float Y
		{
			get { return _y; }
			set
			{
				_y = (value % Map.Height + Map.Height) % Map.Height;
				if (_y > Map.Height / 2) _y -= Map.Height;
			}
		}

		/// <summary>
		/// The map that the vector resides in. An RftVector only makes sense in the context of a Rft map.
		/// </summary>
		public static Rft Map;

		/// <summary>
		/// Constructs a new RftVector with coords (0, 0).
		/// </summary>
		/// <param name="map">The map to wrap RftVectors by</param>
		public RftVector(Rft map)
		{
			Map = map;
			this._x = 0;
			this._y = 0;
		}

		/// <summary>
		/// Constructs a new RftVector with coords (x, y) modulo map dimensions.
		/// </summary>
		/// <param name="map">The Base RFT map size</param>
		/// <param name="x">The x position</param>
		/// <param name="y">The y position</param>
		public RftVector(Rft map, float x, float y)
		{
			Map = map;
			this._x = (x % map.Width + map.Width) % map.Width;
			this._y = (y % map.Height + map.Height) % map.Height;
			if (this._x > map.Width / 2) this._x -= map.Width;
			if (this._y > map.Height / 2) this._y -= map.Height;
		}

		/// <summary>
		/// Create an instance of an RftVector with coords (x, y)
		/// </summary>
		/// <param name="x">The x position</param>
		/// <param name="y">The y position</param>
		/// <exception cref="NotSupportedException">If the RftVector's static 'Map' has not been defined, an error is thrown</exception>
		public RftVector(float x, float y)
		{
			if (Map == null)
				throw new NotSupportedException("Cannot initialize an RftVector without having previously defined the Map.");
			this._x = (x % Map.Width + Map.Width) % Map.Width;
			this._y = (y % Map.Height + Map.Height) % Map.Height;
			if (this._x > Map.Width / 2) this._x -= Map.Width;
			if (this._y > Map.Height / 2) this._y -= Map.Height;
		}

		/// <summary>
		/// Constructs a new RftVector with coords (v.x, v.y) modulo map dimensions.
		/// </summary>
		public RftVector(Rft map, Vector2 v)
		{
			Map = map;
			this._x = (v.X % map.Width + map.Width) % map.Width;
			this._y = (v.Y % map.Height + map.Height) % map.Height;
			if (this._x > map.Width / 2) this._x -= map.Width;
			if (this._y > map.Height / 2) this._y -= map.Height;
		}

		// Use (b-a).Magnitude();
		// public float Dist(RftVector a, RftVector b) { return (b-a).Magnitude(); }

		/// <summary>
		/// Returns float: the magnitude of the RftVector as if it were a Vector2.
		/// </summary>
		public float Length() {return (float)Math.Sqrt(_x*_x + _y*_y);}

		/// <summary>
		/// Returns Vector2: the RftVector normalized to have magnitude 1. (0, 0) normalized will return (1, 0).
		/// </summary>
		public RftVector Normalize()
		{
			if ((this._x == 0) && (this._y == 0)) { return new RftVector(1, 0); }
			return new RftVector(_x / this.Length(), _y / this.Length());
		}

		/// <summary>
		/// Returns a Vector2 from the RftVector
		/// </summary>
		/// <returns>A Vector2 representing the RftVector</returns>
		public Vector2 ToVector2()
		{
			return new Vector2(this._x, this._y);
		}

		/// <summary>
		/// No args: returns 3x3 lattice centered at origin. 8 args: returns sufficient lattice to cover viewport.
		/// </summary>
		// Implemented directly in subterfuge-unity instead.
		/*public List<Vector2> RenderPos()
		{
			var positions = new List<Vector2>();
			for (int i = 1; i >= -1; i--)
			{
				for (int j = -1; j <= 1; j++)
				{
					positions.Append(new Vector2(j * this.map.width + this._x, i * this.map.height + this._y));
				}
			}
			return positions;
		}

		public List<Vector2> RenderPos(float objLeft, float objRight, float objTop, float objBottom, float objWidth,
			float viewportLeft, float viewportRight, float viewportTop, float viewportBottom)
		{
			var positions = new List<Vector2>();
			for (float i = this._y + (float)Math.Floor((viewportTop+objBottom-this._y)/this.map.height) * this.map.height;
				i > viewportBottom - objTop; i -= this.map.height)
			{
				for (float j = this._x + (float)Math.Floor((viewportLeft+objRight-this._x)/this.map.width) * this.map.width;
					j < viewportRight + objLeft; j += this.map.width)
				{
					positions.Append(new Vector2(j, i));
				}
			}
			return positions;
		}*/

		public static RftVector operator +(RftVector a) => a;
		public static RftVector operator -(RftVector a) => new RftVector(Map, -a._x, -a._y);

		public static RftVector operator +(RftVector a, RftVector b) =>
			new RftVector(Map, a._x + b._x, a._y + b._y);

		public static RftVector operator -(RftVector a, RftVector b) => a + (-b);

		public static RftVector operator *(RftVector a, float scaleBy) =>
			new RftVector(Map, a._x * scaleBy, a._y * scaleBy);
	}
}


text:
namespace Subterfuge.Remake.Core.Topologies
{
	/// <summary>
	/// A rectangular flat torus map. Contains height, width.
	/// </summary>
	public class Rft
	{
		/// <summary>
		/// The height of the rectangular flat torus map.
		/// </summary>
		public float Height;

		/// <summary>
		/// The width of the rectangular flat torus map.
		/// </summary>
		public float Width;

		public Rft(float height, float width)
		{
			this.Height = height;
			this.Width = width;
		}
	}
}


text:
# Core Library
## [Creating a new Game](intro.md)
## [Using the Time Machine](Timing.md)
## [Map and wrapping](mapWrapping.md)
## [Updating Unity clients with new Changes](updatingUnity.md)
## [Client Connections](clientConnections.md)
# Server
## [The Server](backend.md)
## [Changing proto files](modifyingServerInterface.md)


text:
# Changing proto files

When changes are made to the `.proto` files within the `ProtoFiles` project, these files also need to be included in the unity client. To ensure that the unity client
is able to use any new networking messages, you will need to copy the `SubterfugeClient` and the `ProtoGenerated` dlls into unity. To do this, build the `SubterfugeClient` project. Once done,
find the following build files:

`<projectRoot>/Server/SubterfugeClient/obj/Debug/netstandard2.0/SubterfugeClient.dll`

`<projectRoot>/Server/ProtoGenerated/obj/Debug/netstandard2.0/ProtoGenerated.dll`

Copy both of these `.dll` files into the Unity folder and replace the existing files.

`<projectRoot>/Assets/PROTOBUF/`

### Serializing Protobuf Messages

```cs
// To bytes:
ByteArray[] message = ProtoMessage.toByteArray()

// From bytes:
ProtoMessage parsed = ProtoMessage.Parser.parseFrom(message)
```

### Redis

View all of the [Redis commands](https://redis.io/commands) to understand how data is being stored. If you are confused, message @R10t--


text:
# Creating a new Game

In order to create a new game, you can use a combination of the `Game` and `GameConfiguration` objects.
You must first create a new `GameConfiguration` object to tell the `Game` how to generate its state and map.
Once the `GameConfiguration` object has been created, you can pass it into the `Game` constructor to create a new
game. It is important to note that a `GameConfiguration` object requires a list of the players who will be in the game.

For a Multiplayer game, this will be a list of the players in the game, for a single player game these can be players with
a random ID. An example of this is shown below:

```cs
// Create a list of players for the game
List<Player> players = new List<Player>();
players.Add(new Player(1));
players.Add(new Player(2));
players.Add(new Player(3));
players.Add(new Player(4));
// Add more if needed

// pass in players to GameConfiguration constructor
GameConfiguration config = new GameConfiguration(players);

// Configure the map generation as required with the GameConfiguration object.
config.seed = 1234;
config.dormantsPerPlayer = 3;
config.maxiumumOutpostDistance = 100;
config.minimumOutpostDistance = 5;
config.outpostsPerPlayer = 7;

// Pass the game config to the game to start the game.
Game game = new Game(config)
```

###

Once the game has been created, most interaction will be done through the `TimeMachine` class. This class manages the
game's simulation and allows you to advance and rewind through the game as well as get the `GameState` at the current
tick.

The `TimeMachine` is globally accessible and can be obtained anywhere after a `Game` has been created
by using the following snippet:
```cs
TimeMachine timeMachine = Game.timeMachine
```

Once you have access to the `TimeMachine` object, you can get the current game's state with the `getState()` method.
The GameState lets you access anything related to the game. For example, all subs, all outposts, all players,
all specialists, and more. The following code snippet shows how you can use the `GameState` to get some basic info.

```cs
GameState currentState = Game.timeMachine.getState()

// Get all outposts
List<Outpost> outpostList = currentState.getOutposts();
foreach(Outpost o : outpostList) {
    Console.WriteLine(o.getDrillerCount());
}

// Get all subs
List<Sub> subList = currentState.getSubs();
foreach(Sub s : subList) {
    Console.WriteLine(s.getDrillerCount());
}

// Get a list of the players
List<Player> playerList = currentState.getPlayers();
foreach(Player p : playerList) {
    Console.WriteLine(p.getPlayerName());
}

```

There is much more you can do with the `GameState` object and this is further documented by looking at the API
documentation.


text:
# Timing

A majority of the game is all about timing. The `TimeMachine` and `GameTick` objects are extremely important to running
the game's simulation to specific points in time. Let's start with the basics:

### Moving through time

In order to move through time, the `TimeMachine` exposes a few functions that let you run the simulation to specific
points in time. These functions are:

- `advance(int ticks)` advances by `ticks` ticks
- `rewind(int ticks)` rewinds by `ticks` ticks
- `goTo(GameEvent event)` goes to a specific `GameEvent`
- `goTo(GameTick tick)` goes to a specific `GameTick`

These functions let you easily go to specific points in time. After using these functions, you can get the simulated
game at that point in time with `Game.timeMachine.getState()` as normal.

### The GameTick object

In order to get a specific moment in time, the `GameTick` object has a few methods to make this easy. The following
code block shows a number of methods you can use to create a `GameTick` from a specific time.

```
// This creates a GameTick from the current time.
// Note: Do not use DateTime.Now to get the current time.
// Instead use the NtpConnector object to ensure users are getting the DateTime from the server.
// If a Game object has been created, this method calculates the offset from the game's start time
// to determine the current tick
GameTick.fromDate(NtpConnector.GetNetworkTime());

// This creates a GameTick from a tick number.
GameTick.fromTickNumber(55);

// Get the current game's GameTick
Game.timeMachine.getCurrentTick();
```

Once you have obtained a `GameTick` object, you can call `.advance(int)` or `.rewind(int)` on the tick itself to move
relatively to that `GameTick` object. Once you offset yourself from the original, you can then use the `TimeMachine`
to go to your tick with `goTo(offsetGameTick)`.


text:
# The Map

Within the game, the map wraps along the two edges.
This means that if a sub flies off the right edge of the map, it will reappear
on the left side of the map moving in the same direction. While this implementation is not a sphere
 (it is a tarus/donut), this design makes it very easy for players to interact with the game.
 Specifically, this makes it so that players can scroll the map seamlessly on their device. In order
 to perform the wrapping of values from one side of the map to the other, the library uses a class
 called the `Rft Vector`.

### RftVector

Rft is an acronym for Rectangular Flat Torus.

In order to perform this map wrapping, the `RftVector` class implements the map
wrapping automatically. The RftVector uses the `%` (modulo) operator to ensure that objects on the map
stay within the map boundaries. There are two important things to know when using this class.

First: To make use of the `RftVector`, you must initialize the dimensions of its boundary. While
the RftVector indicates a single vector, the class needs to know the dimensions of the map in
order to wrap the coordinates to the correct location. Without setting the boundary size, an exception
 will be thrown. The map boundary for `RftVector`s are automatically set when a `Game()`
object is generated, however if you have not instantiated a `Game()`, you must specify the boundary of the vector.
This can be done by using the `RftVector.map` static variable. Creating a 200x200 map would be done as follows:

 ```cs
// Set the dimentions
RftVector.map = new Rft(200, 200);

// Create a new vector
RftVector myLocation = new RftVector(10, 50);
```

Second: It is important to note that with the `RftVector` the origin (0, 0) is at the CENTER
of the map instead of being in the top left or bottom right corner. This means that in a map of 200x200 the origin (0, 0) is actually at (100, 100) in
the middle of the map. This is because of how the wrapping needs to occur in order for
the `RftVector` to operate the right way. Therefore, a coordinate of (30, 10) with the origin in
the bottom right would actually be a coordinate of `((Width/2)-10, (Height/2)-30)` in Rft.

                |
                |
    ----------------------------
                |
        .       |
                |

 ### Location, Position, and movement

While the coordinates may cause some confusion at first, the implementation of the `RftVector`
class makes performing any coordinate map operations extremely easy.
The `RftVector` has operator overloads that allow adding and subtracting two locations together
(vector math). This makes it very easy to automatically wrap a moving object on the map. All
locations in the game are represented with the `RftVector`. You can easily access the `x` and `y`
components of a vector as well as get the magnitude, and a normalized vector. If more functionality is
required, the RftVector also allows converting to a `Vector2` which is a more comprehensive vector library.

```cs
RftVector myPosition = new RftVector(140, 29);
myVector.x // 140
myVector.y // 29
myVector.Magnitude() // The length of the vector
myVector.Normalize() // returns an `RftVector` of magnitude 1 in the same direction

RftVector myDirection = new RftVector(4, -5);

// Easily add the direction to the position to move
// If you move over the map edge, Rft will automatically wrap.
myPosition += myDirection;
```

When doing vector math, the RftVector will automatically wrap the coordinates.
Consider the following:

```cs
// Set a 200x200 map size; meaning (100, 100) and (-100, -100) are the map extents
RftVector.map = new Rft(200, 200)

// We have a sub at (0, 95)
RftVector myLocation = new RftVector(0, 95);

// We have a velocity of (0, 10);
RftVector myVelocity = new RftVector(0, 10);

// We update our position based on our velocity:
myLocation = myLocation + myVelocity;
```

At this point, the resulting vector would be (0, 105). However, based on our map boundary the
map extremes are at (0, 100), and 0, -100). Thus the resulting point exceeds the (0, 100) bound
by 5 units. With the RftVector implementation, the resulting `myLocation` variable would have
a value of (0, -95); this is a value of 5 units from the left edge of the map.


text:
# Updating Unity Clients

When change have been made to the Core repository, it is very likely that you will want to test
if they are working by playing the game. In order to do this, the class library that is generated
from a build in the Core library needs to be copied into the Unity repository.

### Building the Core library

Once you have some changes that you would like tested, you can perform a 'build' of the Core library
In most IDEs there will be a button in the top toolbar that says 'build' to allow you to do so.
Once the library is built, the output files can be found in the following directory:

`<projectRoot>/SubterfugeCore/obj/Debug/netstandard2.0/`

At this directory, a number of files will be present but the main file of concern is `SubterfugeCore.dll`.
Copy this file. This is the class library which contains all the code needed to run the game on a client device.

### Updating Unity

In unity, there is a folder called `lib`. Unfortunately, you cannot paste files directly in unity
so right click this folder and open it in file explorer (`Show in Explorer`on windows). Once the file
explorer is open, delete the existing `SubterfugeCore` files and paste in the `.dll` that has been created
from your build. Once the new `.dll` has been placed in this directory, Unity will use the updated class
library when running the game.

NOTE: Please commit the `.dll` file with your unity commits. If you make some updates to Unity while using an updated `.dll`
any other developer will need to have the same `.dll` file in order for the game to work.

Also Note: When submitting PRs for the Core and unity repositories, if the Unity update includes a
PR that has been submitted to the core library but is still pending, please link to the open PR
as the PR to Core should be done first.


text:
## Understanding the backend

The backend server uses [gRPC](https://grpc.io/) (Google remote procedure calls) to define its network interface.
In the `Server` folder, you can find all of the projects that make the server work.

### ProtoFiles

This project defines the `.proto` files which define the network calls that can be made. To understand these files,
take a look at the [protobuf language guide](https://developers.google.com/protocol-buffers/docs/proto3).

A basic implementation looks like this:
```
service MyService {
  rpc Login(LoginRequest) returns(LoginResponse) {};
}

message LoginRequest {
  string username = 1;
  string password = 2;
}

message LoginResponse {
  string isSuccess = 1;
}
```

This example defines a method called `Login()` which takes a `LoginRequest` as input and responds with a `LoginResponse`. Protobuf will automatically compile these
network definitions into `.cs` files that can be used within the backend server as well as the main game library. If you make changes to any of the `.proto` files,
building this repository will re-generate the `.cs` files.

### ProtoGenerated

This project contains the generated files from the `ProtoFiles` project. This project should never be modified directly and is automatically populated when the
`ProtoFiles` project is build.

### SubterfugeServer

This project is the game server. Running this project will start a local server on your own machine. This is helpful for debugging as you are able to set breakpoints
and debug the incoming requests in order to make modifications to the server. The server allos users to register, add friends, join games, and submit game events. The server
will also perform server-side validation to ensure that the game-events that users are submitting are valid.

While you can run the server locally, you also need to have the database running in order to save data.
To run the server locally, ensure that you have [docker installed](https://docs.docker.com/get-docker/) as well as [docker-compose](https://docs.docker.com/compose/install/).
Start the database with `docker-compose up -d db`.

Alternatively, start both the database and the server at the same time with `docker-compose up -d`.

### SubterfugeClient

This is a gRPC client that automatically applies authorization headers to requests. This client library should be used for clients to avoid any hassle.


text:
# Networking and Multiplayer

## Starting a local server (optional)

The Subterfuge server saves information like player login information, open lobbies, and the game events for games.
In order to login, create games, and play with other players you will need to contact a running server. This may be the online server
or may also be a local server on your own machine.

Running a server on your machine makes it easier to make modifications to the server on the fly. However, access to the online server
can be used if you are not expecting to make any server changes.

To run the server locally, ensure that you have [docker installed](https://docs.docker.com/get-docker/) as well as [docker-compose](https://docs.docker.com/compose/install/).
Once they have been installed, Clone the core git repository. Once cloned, move into the root directory of the repository and run `docker-compose up -d`. This will start the
server.

### Connecting to a server

Once the server is started, the Core repository provides a GrpcClient implementation which abstracts access to the server.

```cs
// Setup Access Strings:

// String Hostname = "52.14.116.178"; // For hosted server
String Hostname = "localhost"; // For local deployments
int Port = 5000;

// Create the client:
client = new SubterfugeClient.SubterfugeClient(Hostname, Port.ToString());

// Ensure that the client can connect to the server by accessing the health check endpoint
 try
{
    client.HealthCheck(new HealthCheckRequest());
    return isConnected = true;
}
catch (RpcException exception)
{
    client = null;
    return isConnected = false;
}
```

### Making network calls


text:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>

    <IsPackable>false</IsPackable>

    <LangVersion>8</LangVersion>

    <OutputType>Library</OutputType>

    <Nullable>enable</Nullable>

    <RootNamespace>Subterfuge.Remake.Test</RootNamespace>

    <TargetFramework>net7.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
    <PackageReference Include="Moq" Version="4.16.1" />
    <PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
    <PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\SubterfugeCore\SubterfugeCore.csproj" />
  </ItemGroup>

</Project>


text:
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Core;
using Subterfuge.Remake.Core.Entities.Components;
using Subterfuge.Remake.Core.Entities.Positions;
using Subterfuge.Remake.Core.GameEvents.EventPublishers;
using Subterfuge.Remake.Core.Players;
using Subterfuge.Remake.Core.Timing;

namespace Subterfuge.Remake.Test
{
	[TestClass]
	public class FactoryTest
	{
		Game _game;
		TimeMachine _tm;
		Factory _f;
		TestUtils testUtils = new TestUtils();

		private readonly List<Player> players = new List<Player>()
		{
			new Player(new SimpleUser() { Id = "1" })
		};

		[TestInitialize]
		public void Setup()
		{
			GameConfiguration config = testUtils.GetDefaultGameConfiguration(players);
			config.MapConfiguration.OutpostsPerPlayer = 10;
			_game = new Game(config);
			_tm = _game.TimeMachine;
			foreach (Outpost o in _tm.GetState().GetPlayerOutposts(players[0]))
			{
				if (isFactory(o))
				{
					_f = (Factory)o;
					break;
				}
			}
			Assert.IsNotNull(_f);
		}

		[TestMethod]
		public void ProductionEventSuccess()
		{
			var player = _f.GetComponent<DrillerCarrier>().GetOwner();
			var totalDrillers = _game.TimeMachine.GetState().GetPlayerDrillerCount(player);
			var drillerCap = _game.TimeMachine.GetState().GetPlayerDrillerCapacity(player);
			var playerFactoryCount = _game.TimeMachine.GetState()
				.GetPlayerOutposts(player)
				.Count(it => it.GetOutpostType() == OutpostType.Factory);

			var drillerProducer = _f.GetComponent<DrillerProducer>().Producer;
			ProductionEventArgs eventArgs = null;
			drillerProducer.OnResourceProduced += (sender, productionEvent) =>
			{
				eventArgs = productionEvent;
			};

			Assert.IsNotNull(drillerProducer);
			Assert.IsTrue(totalDrillers < drillerCap);
			_tm.GoTo(drillerProducer.GetNextProductionTick());

			Assert.AreEqual(totalDrillers + (eventArgs.ProductionEvent.ValueProduced * playerFactoryCount), _game.TimeMachine.GetState().GetPlayerDrillerCount(player));
		}

		[TestMethod]
		public void AddDrillers()
		{
			int startingDrillers = _f.GetComponent<DrillerCarrier>().GetDrillerCount();

			var drillerProducer = _f.GetComponent<DrillerProducer>();
			ProductionEventArgs eventArgs = null;
			drillerProducer.Producer.OnResourceProduced += (sender, productionEvent) =>
			{
				eventArgs = productionEvent;
			};

			_tm.GoTo(drillerProducer.Producer.GetNextProductionTick());
			int endingDrillers = _f.GetComponent<DrillerCarrier>().GetDrillerCount();
			Assert.AreEqual(endingDrillers - startingDrillers, eventArgs.ProductionEvent.ValueProduced);
		}

		[TestMethod]
		public void FiveDrillerProductions()
		{
			int startingDrillers = _f.GetComponent<DrillerCarrier>().GetDrillerCount();
			var drillerProducer = _f.GetComponent<DrillerProducer>();

			int lastDrillerCount = 0;
			for (int i = 0; i < 5; i++)
			{
				_tm.GoTo(drillerProducer.Producer.GetNextProductionTick());
				var player = _f.GetComponent<DrillerCarrier>().GetOwner();
				var totalDrillers = _game.TimeMachine.GetState().GetPlayerDrillerCount(player);
				var drillerCap = _game.TimeMachine.GetState().GetPlayerDrillerCapacity(player);
				if (totalDrillers < drillerCap)
				{
					lastDrillerCount = _f.GetComponent<DrillerCarrier>().GetDrillerCount() - startingDrillers;
					Assert.AreEqual(Constants.BaseFactoryProductionAmount * (i + 1),
						_f.GetComponent<DrillerCarrier>().GetDrillerCount() - startingDrillers);
				}
				else
				{
					Assert.AreEqual(lastDrillerCount,_f.GetComponent<DrillerCarrier>().GetDrillerCount() - startingDrillers);
				}
			}
		}

		[TestMethod]
		public void RewindProduction()
		{
			int startingDrillers = _f.GetComponent<DrillerCarrier>().GetDrillerCount();
			var drillerProducer = _f.GetComponent<DrillerProducer>().Producer;
			_tm.Advance(drillerProducer.GetTicksPerProductionCycle());
			_tm.GoTo(new GameTick(0));
			Assert.AreEqual(_f.GetComponent<DrillerCarrier>().GetDrillerCount(), startingDrillers);
		}

		private bool isFactory(Outpost o)
		{
			return o.GetOutpostType() == OutpostType.Factory;
		}
	}
}


text:
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Core;
using Subterfuge.Remake.Core.Entities;
using Subterfuge.Remake.Core.Entities.Components;
using Subterfuge.Remake.Core.Entities.Positions;
using Subterfuge.Remake.Core.Players;
using Subterfuge.Remake.Core.Timing;
using Subterfuge.Remake.Core.Topologies;

namespace Subterfuge.Remake.Test
{
    [TestClass]
    public class GamestateTest
    {
        GameState _state;
        Rft _map;
        Player _player1 = new Player(new SimpleUser() { Id = "1" });
        Outpost _outpost;
        Sub _tempSub;
        private TestUtils testUtils = new TestUtils();
        TimeMachine _timeMachine;

        [TestInitialize]
        public void Setup()
        {
            List<Player> players = new List<Player>();

            GameConfiguration config = testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);

            _state = new GameState(config);
            _timeMachine = new TimeMachine(_state);
            _map = new Rft(300,300);
            _outpost = new Generator("0",new RftVector(_map, 0, 0), _player1, _timeMachine);
            _outpost.GetComponent<DrillerCarrier>().AlterDrillers(10);
            _tempSub = new Sub("1", _outpost, _outpost, new GameTick(), 10, _player1, _timeMachine);
        }

        [TestMethod]
        public void Constructor()
        {
            Assert.IsNotNull(_state);
        }

        [TestMethod]
        public void GetCurrentTick()
        {
            Assert.AreEqual(0, _state.GetCurrentTick().GetTick());
        }

        [TestMethod]
        public void GetStartTick()
        {
            Assert.AreEqual(0, _state.GetStartTick().GetTick());
        }

        [TestMethod]
        public void GetSubList()
        {
            //Ensure the sub list is empty
            Assert.AreEqual(0, _state.GetSubList().Count);
        }

        [TestMethod]
        public void GetOutposts()
        {
            // Ensure that no outposts are generated from a default state
            Assert.IsTrue(_state.GetOutposts().Count == 0);
        }

        [TestMethod]
        public void GetPlayers()
        {
            // Ensure that no players are added in a default state
            Assert.IsTrue(_state.GetPlayers().Count == 0);
        }

        [TestMethod]
        public void AddSub()
        {
            //Ensure the sub list is empty
            Assert.AreEqual(0, _state.GetSubList().Count);

            _state.AddSub(this._tempSub);

            //Ensure the sub was added
            Assert.AreEqual(1, _state.GetSubList().Count);
            Assert.AreEqual(_tempSub, _state.GetSubList()[0]);
        }

        [TestMethod]
        public void RemoveSub()
        {
            //Ensure the sub list is empty
            AddSub();

            _state.RemoveSub(_tempSub);

            //Ensure the sub list is empty
            Assert.AreEqual(0, _state.GetSubList().Count);
        }

        [TestMethod]
        public void SubExists()
        {
            //Ensure the sub is not in the list
            Assert.IsTrue(!_state.SubExists(_tempSub));

            //Ensure the sub list is empty
            AddSub();

            //Ensure the sub is in the list
            Assert.IsTrue(_state.SubExists(_tempSub));

            _state.RemoveSub(_tempSub);

            //Ensure the sub is not in the list
            Assert.IsTrue(!_state.SubExists(_tempSub));
        }

        // TODO: Re-enabled this
        // [TestMethod]
        public void getSubsOnPath()
        {
            //Ensure the sub list is empty
            AddSub();

            //Ensure the sub is on the path between the outposts.
            Assert.AreEqual(_tempSub, _state.getSubsOnPath(_outpost, _outpost)[0]);
        }

        [TestMethod]
        public void GetPlayerSubs()
        {
            //Ensure the sub list is empty
            Assert.AreEqual(0, _state.GetPlayerSubs(_player1).Count);

            // Add a sub
            AddSub();

            //Ensure the sub is returned.
            Assert.AreEqual(_tempSub, _state.GetPlayerSubs(_player1)[0]);
        }

        [TestMethod]
        public void GetPlayerOutposts()
        {
            // No current way to test this.
        }

    }
}


text:
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Core;
using Subterfuge.Remake.Core.Entities;
using Subterfuge.Remake.Core.Entities.Components;
using Subterfuge.Remake.Core.Entities.Positions;
using Subterfuge.Remake.Core.GameEvents.Base;
using Subterfuge.Remake.Core.GameEvents.Combat;
using Subterfuge.Remake.Core.GameEvents.PlayerTriggeredEvents;
using Subterfuge.Remake.Core.GameEvents.SpecialistEvents;
using Subterfuge.Remake.Core.Players;
using Subterfuge.Remake.Core.Timing;
using Subterfuge.Remake.Core.Topologies;

namespace Subterfuge.Remake.Test
{
    [TestClass]
    public class TimeMachineTest
    {
        TestUtils testUtils = new TestUtils();
        Player player = new Player(new SimpleUser() { Id = "1" });
        private Game _game;

        [TestInitialize]
        public void Setup()
        {
            _game = new Game(testUtils.GetDefaultGameConfiguration(new List<Player> { player }));

        }

        [TestMethod]
        public void Constructor()
        {
            Assert.IsNotNull(_game.TimeMachine);
            Assert.IsNotNull(_game.TimeMachine.GetState());
        }

        [TestMethod]
        public void AddEvent()
        {
            Rft map = new Rft(3000, 3000);
            Outpost outpost = new Generator("0", new RftVector(map, 0, 0), player, _game.TimeMachine);
            outpost.GetComponent<DrillerCarrier>().AlterDrillers(10);
            Sub sub = new Sub("1", outpost, outpost, new GameTick(10), 10, player, _game.TimeMachine);
            CombatEvent arriveEvent = new CombatEvent(sub, outpost, new GameTick(10));

            _game.TimeMachine.AddEvent(arriveEvent);
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
            Assert.AreEqual(arriveEvent, _game.TimeMachine.GetFutureEventsOf<CombatEvent>()[0]);
        }

        [TestMethod]
        public void CanAdvanceTime()
        {
            GameTick initialTick = _game.TimeMachine.GetCurrentTick();
            _game.TimeMachine.Advance(5);

            Assert.IsTrue(initialTick < _game.TimeMachine.GetCurrentTick());
            Assert.AreEqual(initialTick.Advance(5).GetTick(), _game.TimeMachine.GetCurrentTick().GetTick());
        }

        [TestMethod]
        public void CanRewindTime()
        {
            GameTick initialTick = _game.TimeMachine.GetCurrentTick();
            _game.TimeMachine.Advance(5);

            Assert.IsTrue(initialTick < _game.TimeMachine.GetCurrentTick());
            Assert.AreEqual(initialTick.Advance(5).GetTick(), _game.TimeMachine.GetCurrentTick().GetTick());

            GameTick advancedTick = _game.TimeMachine.GetCurrentTick();

            _game.TimeMachine.Rewind(1);

            Assert.IsTrue(advancedTick > _game.TimeMachine.GetCurrentTick());
            Assert.AreEqual(advancedTick.Rewind(1).GetTick(), _game.TimeMachine.GetCurrentTick().GetTick());
        }

        [TestMethod]
        public void EventsSwitchQueuesWhenPassedForward()
        {
            Rft map = new Rft(3000, 3000);
            Outpost outpost = new Generator("0", new RftVector(map, 0, 0), player, _game.TimeMachine);
            outpost.GetComponent<DrillerCarrier>().AlterDrillers(10);
            Sub sub = new Sub("1", outpost, outpost, new GameTick(), 10, player, _game.TimeMachine);
            CombatEvent arriveEvent = new CombatEvent(sub, outpost, new GameTick(5));

            _game.TimeMachine.AddEvent(arriveEvent);
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
            Assert.AreEqual(arriveEvent, _game.TimeMachine.GetFutureEventsOf<CombatEvent>()[0]);

            // Go past the tick
            _game.TimeMachine.Advance(6);
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
        }

        [TestMethod]
        public void NaturalEventsAreRemovedWhenRewind()
        {
            Rft map = new Rft(3000, 3000);
            Outpost outpost = new Generator("0", new RftVector(map, 0, 0), player, _game.TimeMachine);
            outpost.GetComponent<DrillerCarrier>().AlterDrillers(10);
            Sub sub = new Sub("1", outpost, outpost, new GameTick(), 10, player, _game.TimeMachine);
            CombatEvent arriveEvent = new CombatEvent(sub, outpost, new GameTick(5));

            _game.TimeMachine.AddEvent(arriveEvent);
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
            Assert.AreEqual(arriveEvent, _game.TimeMachine.GetFutureEventsOf<CombatEvent>()[0]);

            // Go past the tick
            _game.TimeMachine.Advance(6);
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);

            // Rewind back
            _game.TimeMachine.Rewind(6);
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
        }

        [TestMethod]
        public void PlayerEventsAreNotRemovedWhenRewind()
        {
            Rft map = new Rft(3000, 3000);
            Outpost outpost = new Generator("0", new RftVector(map, 0, 0), player, _game.TimeMachine);
            _game.TimeMachine.GetState().AddOutpost(outpost);
            var toggleShield = new ToggleShieldEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.ToggleShieldEventData,
                    OccursAtTick = 10,
                    SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData()
                    {
                        SourceId = outpost.GetComponent<IdentityManager>().GetId()
                    })
                },
                Id = "a",
                IssuedBy = new SimpleUser(),
                RoomId = "1",
                TimeIssued = DateTime.UtcNow,
            });

            _game.TimeMachine.AddEvent(toggleShield);
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<ToggleShieldEvent>().Count);
            Assert.AreEqual(toggleShield, _game.TimeMachine.GetFutureEventsOf<ToggleShieldEvent>()[0]);

            // Go past the tick
            _game.TimeMachine.GoTo(toggleShield.OccursAt);
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<ToggleShieldEvent>().Count);
            Assert.IsFalse(outpost.GetComponent<ShieldManager>().IsShieldActive());

            // Rewind back
            _game.TimeMachine.GoTo(new GameTick(0));
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<ToggleShieldEvent>().Count);
            Assert.IsTrue(outpost.GetComponent<ShieldManager>().IsShieldActive());

            // Go past the tick
            _game.TimeMachine.GoTo(toggleShield.OccursAt);
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<ToggleShieldEvent>().Count);
            Assert.IsFalse(outpost.GetComponent<ShieldManager>().IsShieldActive());

            // Rewind back
            _game.TimeMachine.GoTo(new GameTick(0));
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<ToggleShieldEvent>().Count);
            Assert.IsTrue(outpost.GetComponent<ShieldManager>().IsShieldActive());
        }

        [TestMethod]
        public void CanRemoveEvents()
        {
            Rft map = new Rft(3000, 3000);
            Outpost outpost = new Generator("0", new RftVector(map, 0, 0), player, _game.TimeMachine);
            outpost.GetComponent<DrillerCarrier>().AlterDrillers(10);
            Sub sub = new Sub("1", outpost, outpost, new GameTick(), 10, player, _game.TimeMachine);
            CombatEvent arriveEvent = new CombatEvent(sub, outpost, new GameTick(5));

            _game.TimeMachine.AddEvent(arriveEvent);
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
            Assert.AreEqual(arriveEvent, _game.TimeMachine.GetFutureEventsOf<CombatEvent>()[0]);

            _game.TimeMachine.RemoveEvent(arriveEvent);
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
        }

        [TestMethod]
        public void CanGoToAGameTick()
        {

            GameTick initialTick = _game.TimeMachine.GetCurrentTick();
            _game.TimeMachine.GoTo(new GameTick(5));

            Assert.IsTrue(initialTick < _game.TimeMachine.GetCurrentTick());
            Assert.AreEqual(initialTick.Advance(5).GetTick(), _game.TimeMachine.GetCurrentTick().GetTick());
        }

        [TestMethod]
        public void CanGoToAnEvent()
        {
            Rft map = new Rft(3000, 3000);
            Outpost outpost = new Generator("0", new RftVector(map, 0, 0), player, _game.TimeMachine);
            outpost.GetComponent<DrillerCarrier>().AlterDrillers(10);
            Sub sub = new Sub("1", outpost, outpost, new GameTick(), 10, player, _game.TimeMachine);
            CombatEvent arriveEvent = new CombatEvent(sub, outpost, new GameTick(5));

            _game.TimeMachine.AddEvent(arriveEvent);
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
            Assert.AreEqual(arriveEvent, _game.TimeMachine.GetFutureEventsOf<CombatEvent>()[0]);

            _game.TimeMachine.GoTo(arriveEvent);
            Assert.AreEqual(arriveEvent.OccursAt.GetTick(), _game.TimeMachine.GetCurrentTick().GetTick());
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<CombatEvent>().Count);
        }

        [TestMethod]
        public void CreatingTwoOfTheSameEventWillNotAddThemBoth()
        {
            // Simulate two events being published.
            var eventOne = new NoOpGameEvent(new GameTick(42));
            var eventTwo = new NoOpGameEvent(new GameTick(42));

            _game.TimeMachine.AddEvents(new List<GameEvent>() { eventOne, eventTwo });
            // Ensure only one event got added.
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
        }

        [TestMethod]
        public void PausingTheGamePreventsActionsFromOccuringUntilTheGameIsUnpaused()
        {
            var initialEventTick = 42;
            // Simulate two events being published.
            var noopEvent = new NoOpGameEvent(new GameTick(initialEventTick));

            _game.TimeMachine.AddEvent(noopEvent);
            // Ensure only one event got added.
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);

            // Add a Pause Event at Tick 10,
            // Add an unpause event at Tick 20.
            // Effectively adds 10 ticks to the NoOp Event.
            var startPause = 10;
            var endPause = 20;
            var pauseTen = CreatePauseAt(startPause);
            var unpauseTwenty = CreateUnpauseAt(endPause);
            _game.TimeMachine.AddEvent(pauseTen);
            _game.TimeMachine.AddEvent(unpauseTwenty);

            _game.TimeMachine.GoTo(new GameTick(9));
            // Ensure all events exist as normal.
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>().Count);
            Assert.AreEqual(startPause, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>().Count);
            Assert.AreEqual(endPause, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>()[0].OccursAt.GetTick());

            // Advance to inside the pause event.
            _game.TimeMachine.GoTo(new GameTick(15));
            // Ensure that events other than the Unpause event got pushed.
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick + 5, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>().Count);

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>().Count);
            Assert.AreEqual(endPause, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>()[0].OccursAt.GetTick());

            // Advance to the unpause event
            _game.TimeMachine.GoTo(new GameTick(20));
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick + 10, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>().Count);
            Assert.AreEqual(0, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>().Count);

            // Advance after the unpause to ensure the events are not getting pushed anymore.
            _game.TimeMachine.GoTo(new GameTick(25));
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick + 10, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());
        }

        [TestMethod]
        public void CanReverseAPauseEvent()
        {
            var initialEventTick = 42;
            // Simulate two events being published.
            var noopEvent = new NoOpGameEvent(new GameTick(initialEventTick));

            _game.TimeMachine.AddEvent(noopEvent);
            // Ensure only one event got added.
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);

            // Add a Pause Event at Tick 10,
            // Add an unpause event at Tick 20.
            // Effectively adds 10 ticks to the NoOp Event.
            var startPause = 10;
            var endPause = 20;
            var pauseTen = CreatePauseAt(startPause);
            var unpauseTwenty = CreateUnpauseAt(endPause);
            _game.TimeMachine.AddEvent(pauseTen);
            _game.TimeMachine.AddEvent(unpauseTwenty);

            // Ensure all events exist as normal.
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>().Count);
            Assert.AreEqual(startPause, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>().Count);
            Assert.AreEqual(endPause, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>()[0].OccursAt.GetTick());

            // Advance to after the pause event.
            _game.TimeMachine.GoTo(new GameTick(45));
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick + 10, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());

            // Go back to before the unpause event and ensure events are not pushed.
            _game.TimeMachine.GoTo(new GameTick(0));

            // Ensure pushed events get pulled back
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>().Count);
            Assert.AreEqual(startPause, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>().Count);
            Assert.AreEqual(endPause, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>()[0].OccursAt.GetTick());
        }

        [TestMethod]
        public void OnTickDoesNotOccurWhilePaused()
        {
            var initialEventTick = 42;
            // Simulate two events being published.
            var noopEvent = new NoOpGameEvent(new GameTick(initialEventTick));

            _game.TimeMachine.AddEvent(noopEvent);
            // Ensure only one event got added.
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);

            // Add a Pause Event at Tick 10,
            // Add an unpause event at Tick 20.
            // Effectively adds 10 ticks to the NoOp Event.
            var startPause = 10;
            var endPause = 20;
            var pauseTen = CreatePauseAt(startPause);
            var unpauseTwenty = CreateUnpauseAt(endPause);
            _game.TimeMachine.AddEvent(pauseTen);
            _game.TimeMachine.AddEvent(unpauseTwenty);

            var onTickCounter = 0;
            _game.TimeMachine.OnTick += (timeMachine, onTickArgs) =>
            {
                onTickCounter++;
            };

            // Ensure all events exist as normal.
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>().Count);
            Assert.AreEqual(startPause, _game.TimeMachine.GetFutureEventsOf<PauseGameEvent>()[0].OccursAt.GetTick());

            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>().Count);
            Assert.AreEqual(endPause, _game.TimeMachine.GetFutureEventsOf<UnpauseGameEvent>()[0].OccursAt.GetTick());

            // Advance to after the pause event.
            var progressedTicks = 45;
            _game.TimeMachine.GoTo(new GameTick(progressedTicks));
            Assert.AreEqual(1, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>().Count);
            Assert.AreEqual(initialEventTick + 10, _game.TimeMachine.GetFutureEventsOf<NoOpGameEvent>()[0].OccursAt.GetTick());

            // Ensure that 10 ticks were paused.
            Assert.AreEqual(progressedTicks - 10, onTickCounter);
        }

        private PauseGameEvent CreatePauseAt(int tick)
        {
            return new PauseGameEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.PauseGameEventData,
                    OccursAtTick = tick,
                    SerializedEventData = JsonConvert.SerializeObject(new PauseGameEventData()
                    {
                        TimePaused = DateTime.UtcNow
                    })
                }
            });
        }

        private UnpauseGameEvent CreateUnpauseAt(int tick)
        {
            return new UnpauseGameEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.UnpauseGameEventData,
                    OccursAtTick = tick,
                    SerializedEventData = JsonConvert.SerializeObject(new UnpauseGameEventData()
                    {
                        TimeUnpaused = DateTime.UtcNow
                    })
                }
            });
        }

    }
}


text:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Subterfuge.Remake.Core.Timing;

namespace Subterfuge.Remake.Test
{
    [TestClass]
    public class SeededRandomTest
    {

        [TestMethod]
        public void SameSeedTest()
        {
            int seed = 1;
            SeededRandom rand1 = new SeededRandom(seed);
            SeededRandom rand2 = new SeededRandom(seed);

            for(int i = 0; i < 1000; i++)
            {
                Assert.AreEqual(rand1.NextDouble(), rand2.NextDouble());
            }
            for (int i = 0; i < 1000; i++)
            {
                Assert.AreEqual(rand1.NextRand(0, 10), rand2.NextRand(0, 10));
            }
            for (int i = 0; i < 1000; i++)
            {
                Assert.AreEqual(rand1.NextDouble(), rand2.NextDouble());
                Assert.AreEqual(rand1.NextRand(0, 10), rand2.NextRand(0, 10));
            }
        }

        [TestMethod]
        public void IndexedRand()
        {
            int seed = 1234;
            SeededRandom rand1 = new SeededRandom(seed);
            SeededRandom rand2 = new SeededRandom(seed);

            Assert.AreEqual(rand1.GetDouble(100), rand2.GetDouble(100));
            Assert.AreEqual(rand1.GetRand(200, 0, 10), rand2.GetRand(200, 0, 10));
        }

    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Core;
using Subterfuge.Remake.Core.Entities.Components;
using Subterfuge.Remake.Core.Entities.Positions;
using Subterfuge.Remake.Core.Generation;
using Subterfuge.Remake.Core.Players;
using Subterfuge.Remake.Core.Timing;

namespace Subterfuge.Remake.Test
{
    [TestClass]
    public class MapGeneratorTest
    {
        private readonly TestUtils _testUtils = new TestUtils();
        private TimeMachine _timeMachine;

        List<Player> players = new List<Player>
        {
            new Player(new SimpleUser() { Id = "1" }),
            new Player(new SimpleUser() { Id = "2" }),
            new Player(new SimpleUser() { Id = "3" }),
            new Player(new SimpleUser() { Id = "4" })
        };

        [TestInitialize]
        public void Setup()
        {
            _timeMachine = new TimeMachine(new GameState(players));
            GameConfiguration config = new TestUtils().GetDefaultGameConfiguration(players);
            new Game(config);
        }

        [TestMethod]
        public void Constructor()
        {

            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 3;
            config.MapConfiguration.MaximumOutpostDistance = 100;
            config.MapConfiguration.MinimumOutpostDistance = 5;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            Assert.IsNotNull(generator);
        }

        [TestMethod]
        public void GeneratesTheRightNumberOfOutposts()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 3;
            config.MapConfiguration.MaximumOutpostDistance = 100;
            config.MapConfiguration.MinimumOutpostDistance = 5;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();
            Assert.AreEqual(config.PlayersInLobby.Count * (config.MapConfiguration.OutpostsPerPlayer + config.MapConfiguration.DormantsPerPlayer), generatedOutposts.Count);
        }

        [TestMethod]
        public void GeneratesOutpostsForAllPlayers()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 0;
            config.MapConfiguration.MaximumOutpostDistance = 100;
            config.MapConfiguration.MinimumOutpostDistance = 5;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            List<Player> playersGenerated = new List<Player>();
            foreach (Outpost outpost in generatedOutposts)
            {
                if(!playersGenerated.Contains(outpost.GetComponent<DrillerCarrier>().GetOwner()))
                    playersGenerated.Add(outpost.GetComponent<DrillerCarrier>().GetOwner());
            }

            Assert.AreEqual(config.PlayersInLobby.Count, playersGenerated.Count);
            Assert.AreEqual(config.PlayersInLobby.Count * config.MapConfiguration.OutpostsPerPlayer, generatedOutposts.Count);
        }

        [TestMethod]
        public void GeneratesEqualOutpostsForAllPlayers()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 3;
            config.MapConfiguration.MaximumOutpostDistance = 100;
            config.MapConfiguration.MinimumOutpostDistance = 5;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            Dictionary<Player, int> outpostCounts = new Dictionary<Player, int>();
            foreach (Outpost outpost in generatedOutposts)
            {
                // Ignore dormant outposts
                if (outpost.GetComponent<DrillerCarrier>().GetOwner() != null)
                {
                    if (!outpostCounts.ContainsKey(outpost.GetComponent<DrillerCarrier>().GetOwner()))
                        outpostCounts.Add(outpost.GetComponent<DrillerCarrier>().GetOwner(), 1);
                    else
                        outpostCounts[outpost.GetComponent<DrillerCarrier>().GetOwner()]++;
                }
            }

            foreach (KeyValuePair<Player, int> keyValuePair in outpostCounts)
            {
                Assert.AreEqual(config.MapConfiguration.OutpostsPerPlayer, keyValuePair.Value);
            }
        }

        [TestMethod]
        public void UnownedOutpostsHaveNoDrillers()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 3;
            config.MapConfiguration.MaximumOutpostDistance = 100;
            config.MapConfiguration.MinimumOutpostDistance = 5;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            // Loop through all unowned outpost and verify that the driller count is 0 for each
            foreach (Outpost outpost in generatedOutposts.Where(x => x.GetComponent<DrillerCarrier>().GetOwner() == null))
            {
                Assert.AreEqual(0, outpost.GetComponent<DrillerCarrier>().GetDrillerCount());
            }
        }

        [TestMethod]
        public void UnownedOutpostsHaveNoShieldGeneration()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 3;
            config.MapConfiguration.MaximumOutpostDistance = 100;
            config.MapConfiguration.MinimumOutpostDistance = 5;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            // Advance the time forward until next shield production
            _timeMachine.Advance(Constants.BASE_SHIELD_REGENERATION_TICKS);

            // Check that each unowned outpost has not generated shields
            foreach (Outpost outpost in generatedOutposts.Where(x => x.GetComponent<DrillerCarrier>().GetOwner() == null))
            {
                Assert.AreEqual(0, outpost.GetComponent<ShieldManager>().GetShields());
            }
        }

        [TestMethod]
        public void UnownedOutpostsHaveNoDrillerProduction()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 3;
            config.MapConfiguration.MaximumOutpostDistance = 100;
            config.MapConfiguration.MinimumOutpostDistance = 5;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            // Advance the time forward until next production
            _timeMachine.Advance(Constants.TicksPerProduction);

            // Check that each unowned outpost has not produced drillers
            foreach (Outpost outpost in generatedOutposts.Where(x => x.GetComponent<DrillerCarrier>().GetOwner() == null))
            {
                Assert.AreEqual(0, outpost.GetComponent<DrillerCarrier>().GetDrillerCount());
            }
        }

        [TestMethod]
        public void AllPlayersHaveAQueen()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 3;
            config.MapConfiguration.MaximumOutpostDistance = 100;
            config.MapConfiguration.MinimumOutpostDistance = 5;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            Dictionary<Player, int> queenCounts = new Dictionary<Player, int>();
            foreach (Outpost outpost in generatedOutposts)
            {
                // Ignore dormant outposts
                if (outpost.GetComponent<DrillerCarrier>().GetOwner() != null && outpost.GetComponent<SpecialistManager>().GetUncapturedSpecialistCount() == 1)
                {
                    if (!queenCounts.ContainsKey(outpost.GetComponent<DrillerCarrier>().GetOwner()))
                        queenCounts.Add(outpost.GetComponent<DrillerCarrier>().GetOwner(), 1);
                    else
                        queenCounts[outpost.GetComponent<DrillerCarrier>().GetOwner()]++;
                }
            }

            foreach (KeyValuePair<Player, int> keyValuePair in queenCounts)
            {
                Assert.AreEqual(1, keyValuePair.Value);
            }
        }

        [TestMethod]
        public void MaxOutpostDistanceRespected()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 0;
            config.MapConfiguration.MaximumOutpostDistance = 0;
            config.MapConfiguration.MinimumOutpostDistance = 0;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            // Ensure all 7 outposts were generated on top of each other.
            // Should be at 0,0
            foreach (Outpost o in generatedOutposts)
            {
                Assert.AreEqual(0, o.GetComponent<PositionManager>().CurrentLocation.X);
                Assert.AreEqual(0, o.GetComponent<PositionManager>().CurrentLocation.Y);
            }
        }

        [TestMethod]
        public void OutpostsPerPlayerRespected()
        {
            // List<Player> players = new List<Player> { new Player("1") };

            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 0;
            config.MapConfiguration.MaximumOutpostDistance = 0;
            config.MapConfiguration.MinimumOutpostDistance = 0;
            config.MapConfiguration.OutpostsPerPlayer = 7;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            // Ensure all 7 outposts were generated on top of each other.
            // Should be at 0,0
            Assert.AreEqual(config.MapConfiguration.OutpostsPerPlayer * players.Count, generatedOutposts.Count);
        }

        [TestMethod]
        [ExpectedException(typeof(PlayerCountException))]
        public void CannotCreateGameWithNoPlayers()
        {
            List<Player> players = new List<Player>();
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            new MapGenerator(config.MapConfiguration, players, _timeMachine);

        }

        [TestMethod]
        [ExpectedException(typeof(OutpostPerPlayerException))]
        public void cannotCreateGameWithAtLeastOneOutpostPerPlayer()
        {
            // List<Player> players = new List<Player> { new Player("1") };
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            config.MapConfiguration.OutpostsPerPlayer = 0;
            new MapGenerator(config.MapConfiguration, players, _timeMachine);

        }

        [TestMethod]
        public void DormantsPerPlayerRespected()
        {
            // List<Player> players = new List<Player> { new Player("1") };

            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 7;
            config.MapConfiguration.MaximumOutpostDistance = 0;
            config.MapConfiguration.MinimumOutpostDistance = 0;
            config.MapConfiguration.OutpostsPerPlayer = 1;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            // Ensure all 7 outposts were generated
            // Ensure they all have no owner.
            int dormants = 0;
            foreach (Outpost o in generatedOutposts)
            {
                if (o.GetComponent<DrillerCarrier>().GetOwner() == null)
                {
                    dormants++;
                }
            }
            Assert.AreEqual(config.MapConfiguration.DormantsPerPlayer * players.Count, dormants);
        }

        [TestMethod]
        public void MinimumOutpostDistanceRespected()
        {
            // List<Player> players = new List<Player> { new Player("1") };

            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 0;
            config.MapConfiguration.MaximumOutpostDistance = 2;
            config.MapConfiguration.MinimumOutpostDistance = 1;
            config.MapConfiguration.OutpostsPerPlayer = 2;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            // Ensure the distance between outposts is over 199.
            Assert.AreEqual(config.MapConfiguration.OutpostsPerPlayer * players.Count, generatedOutposts.Count);
            // Ensure the distance between the two is respected.
            Outpost outpost1 = generatedOutposts[0];
            Outpost outpost2 = generatedOutposts[1];

            float distance = (outpost1.GetComponent<PositionManager>().CurrentLocation-outpost2.GetComponent<PositionManager>().CurrentLocation).Length();
            Assert.IsTrue(distance >= config.MapConfiguration.MinimumOutpostDistance);
        }

        [TestMethod]
        public void AllOutpostsHaveUniqueNames()
        {
            GameConfiguration config = _testUtils.GetDefaultGameConfiguration(players);
            Assert.IsNotNull(config);
            Random rand = new Random(DateTime.UtcNow.Millisecond);
            config.MapConfiguration.Seed = rand.Next();
            config.MapConfiguration.DormantsPerPlayer = 3;
            config.MapConfiguration.MaximumOutpostDistance = 200;
            config.MapConfiguration.MinimumOutpostDistance = 20;
            config.MapConfiguration.OutpostsPerPlayer = 3;

            MapGenerator generator = new MapGenerator(config.MapConfiguration, players, _timeMachine);
            List<Outpost> generatedOutposts = generator.GenerateMap();

            Assert.AreEqual(generatedOutposts.Select(x => x.GetComponent<IdentityManager>().GetName()).Distinct().Count(), generatedOutposts.Count);
        }

    }
}


text:
using System;
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Subterfuge.Remake.Core.Topologies;

namespace Subterfuge.Remake.Test
{
    [TestClass]
    public class RftVectorTest
    {

        [TestMethod]
        public void GettersAndSetters()
        {
            int mapDimensions = 100;
            int pointDimensions = 50;

            Rft map = new Rft(mapDimensions, mapDimensions);
            RftVector vectorTest = new RftVector(map, pointDimensions, pointDimensions);

            Assert.AreEqual(pointDimensions, vectorTest.X);
            Assert.AreEqual(pointDimensions, vectorTest.Y);
            Assert.AreEqual(mapDimensions, map.Height);
            Assert.AreEqual(mapDimensions, map.Width);
        }

        [TestMethod]
        public void GlobalMapSize()
        {
            int mapSize = 100;
            Rft map = new Rft(mapSize, mapSize);

            int firstPointLocation = 25;
            new RftVector(map, firstPointLocation, firstPointLocation);

            Assert.AreEqual(map, RftVector.Map);
        }

        [TestMethod]
        public void RftWrapsPoints()
        {
            int mapDimensions = 100;
            Rft map = new Rft(mapDimensions, mapDimensions);
            for (int i = 0; i < 300; i++)
            {
                RftVector vectorTest = new RftVector(map, i, i);
                int wrappedDimension;

                if ((i % mapDimensions) > mapDimensions / 2)
                {
                    wrappedDimension = (i % mapDimensions) - (mapDimensions);
                }
                else
                {
                    wrappedDimension = (i % mapDimensions);
                }

                Assert.AreEqual(wrappedDimension, vectorTest.X);
                Assert.AreEqual(wrappedDimension, vectorTest.Y);
                Assert.AreEqual(mapDimensions, map.Height);
                Assert.AreEqual(mapDimensions, map.Width);
            }
        }

        [TestMethod]
        public void RftCanChangeMapSize()
        {
            int mapDimensions = 100;
            int pointDimensions = 150;
            int mapDelta = 200;

            int wrappedDimension;
            wrappedDimension = (pointDimensions % mapDimensions);

            Rft map = new Rft(mapDimensions, mapDimensions);
            RftVector vectorTest = new RftVector(map, pointDimensions, pointDimensions);

            Assert.AreEqual(wrappedDimension, vectorTest.X);
            Assert.AreEqual(wrappedDimension, vectorTest.Y);
            Assert.AreEqual(mapDimensions, map.Height);
            Assert.AreEqual(mapDimensions, map.Width);

            RftVector.Map = new Rft(mapDelta, mapDelta);

            wrappedDimension = (pointDimensions % mapDimensions);

            Assert.AreEqual(wrappedDimension, vectorTest.X);
            Assert.AreEqual(wrappedDimension, vectorTest.Y);
            Assert.AreEqual(mapDelta, RftVector.Map.Height);
            Assert.AreEqual(mapDelta, RftVector.Map.Height);
        }

        [TestMethod]
        public void CanGetMagnitude()
        {
            int mapDimension = 100;
            Rft map = new Rft(mapDimension, mapDimension);

            RftVector vector = new RftVector(map, 0, 1);
            Assert.AreEqual(1, vector.Length());

            for (int i = 0; i < 300; i++)
            {
                vector = new RftVector(map, 0, i);
                float position = vector.Y;
                Assert.AreEqual(Math.Abs(position), vector.Length());
            }

            int somePosition = 152;
            RftVector vectorTwo = new RftVector(somePosition, somePosition);
            float wrappedPosition = vectorTwo.X;

            Assert.AreEqual((float)Math.Sqrt(wrappedPosition*wrappedPosition + wrappedPosition*wrappedPosition), vectorTwo.Length());
        }

        [TestMethod]
        public void CanGetVector2()
        {
            int mapDimension = 100;
            Rft map = new Rft(mapDimension, mapDimension);

            for (int i = 0; i < 300; i++)
            {
                RftVector vector = new RftVector(map, 0, i);

                float vectorX = vector.X;
                float vectorY = vector.Y;
                Vector2 duplicate = new Vector2(vectorX, vectorY);

                Vector2 derived = vector.ToVector2();

                Assert.AreEqual(duplicate.X, derived.X);
                Assert.AreEqual(duplicate.Y, derived.Y);
            }
        }

        [TestMethod]
        public void CanNormalize()
        {
            int mapDimension = 100;
            Rft map = new Rft(mapDimension, mapDimension);

            RftVector vector = new RftVector(map, 0, 1);
            Assert.AreEqual(1, vector.Normalize().Length());

            for (int i = 0; i < 300; i++)
            {
                vector = new RftVector(map, 0, i);
                Assert.AreEqual(1, vector.Normalize().Length());
            }
        }

        [TestMethod]
        [ExpectedException(typeof(NotSupportedException))]
        public void CannotMakeVectorWithoutSettingMap()
        {
            RftVector.Map = null;
            new RftVector(123, 123);
        }

        [TestMethod]
        public void CanSubtractVectors()
        {
            int mapDimensions = 100;
            int mapRadius = mapDimensions / 2;
            Rft map = new Rft(mapDimensions, mapDimensions);

            // Create a vector at the edge of the map
            RftVector rightEdgeMap = new RftVector(map, mapRadius - 1, 0);

            // Create a vector at the other edge of the map
            RftVector leftEdgeMap = new RftVector(-mapRadius + 1, 0);

            // Determine the distance between them. Expect 2.
            RftVector difference = rightEdgeMap - leftEdgeMap;
            Assert.AreEqual(2, difference.Length());
            Assert.AreEqual(-2, difference.X);
            Assert.AreEqual(0, difference.Y);
        }

        [TestMethod]
        public void CanAddVectors()
        {
            int mapDimensions = 100;
            int mapRadius = mapDimensions / 2;
            Rft map = new Rft(mapDimensions, mapDimensions);

            // Create a vector at the edge of the map
            RftVector rightEdgeMap = new RftVector(map, mapRadius - 1, 0);

            // Create a vector that makes the edge go over the boarder
            RftVector forceWrap = new RftVector(2, 0);

            // Determine location of new point. Expect opposite map edge.
            RftVector sum = rightEdgeMap + forceWrap;
            Assert.AreEqual(mapRadius - 1, sum.Length());
            Assert.AreEqual(-(mapRadius - 1), sum.X);
            Assert.AreEqual(0, sum.Y);
        }

    }
}


text:
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Core;
using Subterfuge.Remake.Core.Entities;
using Subterfuge.Remake.Core.Entities.Components;
using Subterfuge.Remake.Core.Entities.Positions;
using Subterfuge.Remake.Core.GameEvents.PlayerTriggeredEvents;
using Subterfuge.Remake.Core.Players;
using Subterfuge.Remake.Core.Timing;

namespace Subterfuge.Remake.Test
{

	[TestClass]
	public class DrillMineTest
	{
		Game _game;
		TimeMachine _tm;
		Player _p = new Player(new SimpleUser() { Id = "1" });
		Outpost _o1, _o2;
		GameRoomEvent _model1, _model2;
		TestUtils testUtils = new TestUtils();

		public List<Player> players;

		[TestInitialize]
		public void Setup()
		{
			players = new List<Player>()
			{
				_p,
			};
			GameConfiguration config = testUtils.GetDefaultGameConfiguration(players);
			config.MapConfiguration.OutpostsPerPlayer = 12;
			_game = new Game(config);
			_tm = _game.TimeMachine;
			_o1 = _tm.GetState().GetPlayerOutposts(_p)[0];
			_o2 = _tm.GetState().GetPlayerOutposts(_p)[1];
			_model1 = new GameRoomEvent()
			{
				GameEventData = new GameEventData()
				{
					OccursAtTick = 10,
					EventDataType = EventDataType.DrillMineEventData,
					SerializedEventData = JsonConvert.SerializeObject(new DrillMineEventData()
					{
						SourceId = _o1.GetComponent<IdentityManager>().GetId()
					}),
				},
				Id = Guid.NewGuid().ToString(),
			};
			_model2 = new GameRoomEvent()
			{
				GameEventData = new GameEventData()
				{
					OccursAtTick = 20,
					EventDataType = EventDataType.DrillMineEventData,
					SerializedEventData = JsonConvert.SerializeObject(new DrillMineEventData()
					{
						SourceId = _o2.GetComponent<IdentityManager>().GetId()
					}),
				},
				Id = Guid.NewGuid().ToString(),
			};
		}

		[TestMethod]
		public void DrillMineEventTest()
		{
			Assert.IsNotNull(_model1);
		}

		[TestMethod]
		public void ExtractFromGameEventModel()
		{
			DrillMineEvent drillMine = new DrillMineEvent(_model1);
			IEntity combatable = _tm.GetState().GetEntity(drillMine.GetEventData().SourceId);
			Assert.IsNotNull(combatable);
			Assert.IsTrue(combatable is Outpost);
			Assert.IsFalse(combatable is Mine);
		}

		[TestMethod]
		public void CannotDrillWithInsufficientDrillers()
		{
			DrillMineEvent drillMine = new DrillMineEvent(_model1);
			_tm.AddEvent(drillMine);
			_tm.Advance(10);
			Assert.IsFalse(drillMine.WasEventSuccessful());
		}

		[TestMethod]
		public void DrillFirstMine()
		{
			_o1.GetComponent<DrillerCarrier>().AlterDrillers(50);
			DrillMineEvent drillMine = new DrillMineEvent(_model1);
			_tm.AddEvent(drillMine);
			_tm.Advance(10);
			Assert.IsTrue(drillMine.WasEventSuccessful());
			Assert.IsFalse(_tm.GetState().GetOutposts().Contains(_o1));
		}

		[TestMethod]
		public void CannotDrillMineOrDestroyedOutpost()
		{
			DrillMineEvent drillMine = new DrillMineEvent(_model1);
			DrillMineEvent drillSecondMine = new DrillMineEvent(_model2);
			DrillMineEvent drillMineAgain = new DrillMineEvent(new GameRoomEvent()
			{
				GameEventData = new GameEventData()
				{
					OccursAtTick = 25,
					EventDataType = EventDataType.DrillMineEventData,
					SerializedEventData = JsonConvert.SerializeObject(new DrillMineEventData()
					{
						SourceId = _o1.GetComponent<IdentityManager>().GetId()
					}),
				},
				Id = Guid.NewGuid().ToString(),
			});
			_o1.GetComponent<DrillerCarrier>().AlterDrillers(150);
			_o2.GetComponent<DrillerCarrier>().AlterDrillers(300);
			_o2.GetComponent<DrillerCarrier>().Destroy();
			_tm.AddEvent(drillMine);
			_tm.AddEvent(drillMineAgain);
			_tm.AddEvent(drillSecondMine);
			_tm.Advance(25);
			Assert.IsFalse(drillMineAgain.WasEventSuccessful());
			Assert.IsFalse(drillSecondMine.WasEventSuccessful());
		}

		[TestMethod]
		public void MiningCostIncreases()
		{
			_o1.GetComponent<DrillerCarrier>().AlterDrillers(50);
			_o2.GetComponent<DrillerCarrier>().AlterDrillers(50);
			DrillMineEvent drillFirstMine = new DrillMineEvent(_model1);
			DrillMineEvent drillSecondMine = new DrillMineEvent(_model2);
			_tm.AddEvent(drillFirstMine);
			_tm.AddEvent(drillSecondMine);
			_tm.Advance(20);
			Assert.IsTrue(drillFirstMine.WasEventSuccessful());
			Assert.IsFalse(drillSecondMine.WasEventSuccessful());
			_tm.Rewind(20);
			_o2.GetComponent<DrillerCarrier>().AlterDrillers(100);
			_tm.Advance(20);
			Assert.IsTrue(drillSecondMine.WasEventSuccessful());
			Assert.AreEqual(200, _o1.GetComponent<DrillerCarrier>().GetOwner().GetRequiredDrillersToMine());
		}

		[TestMethod]
		public void RegularNeptuniumProduction()
		{
			_o1.GetComponent<DrillerCarrier>().AlterDrillers(50);
			DrillMineEvent drillMine = new DrillMineEvent(_model1);
			_tm.AddEvent(drillMine);
			_tm.Advance(10);
			NeptuniumProducer resourceProducer = drillMine.CreatedMine.GetComponent<NeptuniumProducer>();
			_tm.GoTo(resourceProducer.Producer.GetNextProductionTick());
			Assert.AreEqual(12, _o1.GetComponent<DrillerCarrier>().GetOwner().GetNeptunium());
		}

		[TestMethod]
		public void RewindTest()
		{
			var drillerCarrier = _o1.GetComponent<DrillerCarrier>();
			drillerCarrier.AlterDrillers(50);
			var initialDrillers = drillerCarrier.GetDrillerCount();

			DrillMineEvent drillMine = new DrillMineEvent(_model1);
			_tm.AddEvent(drillMine);
			_tm.GoTo(drillMine.OccursAt);

			NeptuniumProducer resourceProducer = drillMine.CreatedMine.GetComponent<NeptuniumProducer>();
			_tm.GoTo(resourceProducer.Producer.GetNextProductionTick());

			// Rewind to before the mine was drilled
			_tm.GoTo(drillMine.OccursAt.Rewind(5));
			Assert.IsTrue(_tm.GetState().GetOutposts().Contains(_o1));
			Assert.AreEqual(0, _p.GetNeptunium());
			Assert.AreEqual(5, _tm.GetCurrentTick().GetTick());
			Assert.AreEqual(initialDrillers, _o1.GetComponent<DrillerCarrier>().GetDrillerCount());
		}
	}
}


text:
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Core;
using Subterfuge.Remake.Core.Entities;
using Subterfuge.Remake.Core.Entities.Components;
using Subterfuge.Remake.Core.Entities.Positions;
using Subterfuge.Remake.Core.Entities.Specialists.Specialists;
using Subterfuge.Remake.Core.GameEvents.Base;
using Subterfuge.Remake.Core.GameEvents.PlayerTriggeredEvents;
using Subterfuge.Remake.Core.Players;
using Subterfuge.Remake.Core.Timing;
using Subterfuge.Remake.Core.Topologies;

namespace Subterfuge.Remake.Test
{
    [TestClass]
    public class LaunchEventTest
    {
        private Game _game;
        private TestUtils testUtils = new TestUtils();
        private List<Player> players = new List<Player>
        {
            new Player(new SimpleUser() { Id = "1" }),
            new Player(new SimpleUser() { Id = "2" })
        };

        [TestInitialize]
        public void Setup()
        {
            GameConfiguration config = testUtils.GetDefaultGameConfiguration(players);
            _game = new Game(config);
        }

        [TestMethod]
        public void Constructor()
        {
            Assert.IsNotNull(new LaunchEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    OccursAtTick = 10,
                    EventDataType = EventDataType.LaunchEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
                    {
                        DestinationId = "0",
                        DrillerCount = 10,
                        SourceId = "0",
                    }),
                },
                Id = "123",
            }));
        }

        [TestMethod]
        public void CanLaunchSingleSub()
        {
            Outpost outpost1 = new Generator("0",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            Outpost outpost2 = new Generator("1",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            outpost1.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[0]);
            outpost2.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[1]);
            outpost1.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            outpost2.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            int outpostOneInitial = outpost1.GetComponent<DrillerCarrier>().GetDrillerCount();

            _game.TimeMachine.GetState().GetOutposts().Add(outpost1);
            _game.TimeMachine.GetState().GetOutposts().Add(outpost2);

            LaunchEvent launch = new LaunchEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    OccursAtTick = 1,
                    EventDataType = EventDataType.LaunchEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
                    {
                        DestinationId = outpost2.GetComponent<IdentityManager>().GetId(),
                        DrillerCount = 1,
                        SourceId = outpost1.GetComponent<IdentityManager>().GetId(),
                    }),
                },
                Id = "a",
            });
            Assert.AreEqual(true, launch.ForwardAction(_game.TimeMachine));

            // Ensure the sub was launched, outpost lost drillers, etc.
            Assert.AreEqual(1, _game.TimeMachine.GetState().GetSubList().Count);
            Assert.AreEqual(outpostOneInitial - 1, outpost1.GetComponent<DrillerCarrier>().GetDrillerCount());
        }

        [TestMethod]
        public void CanUndoSubLaunch()
        {
            Outpost outpost1 = new Generator("0",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            Outpost outpost2 = new Generator("1",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            outpost1.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[0]);
            outpost2.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[1]);
            outpost1.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            outpost2.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            int outpostOneInitial = outpost1.GetComponent<DrillerCarrier>().GetDrillerCount();
            int outpostTwoInitial = outpost2.GetComponent<DrillerCarrier>().GetDrillerCount();

            _game.TimeMachine.GetState().GetOutposts().Add(outpost1);
            _game.TimeMachine.GetState().GetOutposts().Add(outpost2);

            LaunchEvent launch = new LaunchEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    OccursAtTick = 1,
                    EventDataType = EventDataType.LaunchEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
                    {
                        DestinationId = outpost2.GetComponent<IdentityManager>().GetId(),
                        DrillerCount = 1,
                        SourceId = outpost1.GetComponent<IdentityManager>().GetId(),
                    }),
                },
                Id = "a",
            });
            Assert.AreEqual(true, launch.ForwardAction(_game.TimeMachine));

            // Ensure the sub was launched, outpost lost drillers, etc.
            Assert.AreEqual(1, _game.TimeMachine.GetState().GetSubList().Count);
            Assert.AreEqual(outpostOneInitial - 1, outpost1.GetComponent<DrillerCarrier>().GetDrillerCount());
            Assert.AreEqual(true, launch.BackwardAction(_game.TimeMachine));
            Assert.AreEqual(outpostOneInitial, outpost1.GetComponent<DrillerCarrier>().GetDrillerCount());
            Assert.AreEqual(outpostTwoInitial, outpost2.GetComponent<DrillerCarrier>().GetDrillerCount());
            Assert.AreEqual(0, _game.TimeMachine.GetState().GetSubList().Count);
        }

        [TestMethod]
        public void CanGetTheLaunchedSub()
        {
            Outpost outpost1 = new Generator("0",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            Outpost outpost2 = new Generator("1",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            outpost1.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            outpost2.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            outpost1.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[0]);
            outpost2.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[1]);
            int outpostOneInitial = outpost1.GetComponent<DrillerCarrier>().GetDrillerCount();

            _game.TimeMachine.GetState().GetOutposts().Add(outpost1);
            _game.TimeMachine.GetState().GetOutposts().Add(outpost2);

            LaunchEvent launch = new LaunchEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    OccursAtTick = 1,
                    EventDataType = EventDataType.LaunchEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
                    {
                        DestinationId = outpost2.GetComponent<IdentityManager>().GetId(),
                        DrillerCount = 1,
                        SourceId = outpost1.GetComponent<IdentityManager>().GetId(),
                    }),
                },
                Id = "a",
            });
            Assert.AreEqual(true, launch.ForwardAction(_game.TimeMachine));

            // Ensure the sub was launched, outpost lost drillers, etc.
            Assert.AreEqual(1, _game.TimeMachine.GetState().GetSubList().Count);
            Assert.AreEqual(outpostOneInitial - 1, outpost1.GetComponent<DrillerCarrier>().GetDrillerCount());

            // Ensure can get the sub.
            Assert.IsNotNull(_game.TimeMachine.GetState().GetSubList()[0]);
            Assert.AreEqual(1, _game.TimeMachine.GetState().GetSubList()[0].GetComponent<DrillerCarrier>().GetDrillerCount());
            // Assert.AreEqual(outpost1, _game.TimeMachine.GetState().GetSubList()[0].GetComponent<PositionManager>().GetSource());
            Assert.AreEqual(outpost2, _game.TimeMachine.GetState().GetSubList()[0].GetComponent<PositionManager>().GetDestination());
        }

        [TestMethod]
        public void SubLaunchCreatesCombatEvents()
        {
            Outpost outpost1 = new Generator("0",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            Outpost outpost2 = new Generator("1",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            outpost1.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            outpost2.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            outpost1.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[0]);
            outpost2.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[1]);
            int outpostOneInitial = outpost1.GetComponent<DrillerCarrier>().GetDrillerCount();
            int outpostTwoInitial = outpost2.GetComponent<DrillerCarrier>().GetDrillerCount();

            _game.TimeMachine.GetState().GetOutposts().Add(outpost1);
            _game.TimeMachine.GetState().GetOutposts().Add(outpost2);

            LaunchEvent launch1 = new LaunchEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    OccursAtTick = 1,
                    EventDataType = EventDataType.LaunchEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
                    {
                        DestinationId = outpost2.GetComponent<IdentityManager>().GetId(),
                        DrillerCount = 1,
                        SourceId = outpost1.GetComponent<IdentityManager>().GetId(),
                    }),
                },
                Id = "a",
            });

            LaunchEvent launch2 = new LaunchEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    OccursAtTick = 1,
                    EventDataType = EventDataType.LaunchEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
                    {
                        DestinationId = outpost1.GetComponent<IdentityManager>().GetId(),
                        DrillerCount = 1,
                        SourceId = outpost2.GetComponent<IdentityManager>().GetId(),
                    }),
                },
                Id = "a",
            });

            Assert.AreEqual(true, launch1.ForwardAction(_game.TimeMachine));
            Assert.AreEqual(true, launch2.ForwardAction(_game.TimeMachine));

            // Ensure the sub was launched, outpost lost drillers, etc.
            Assert.AreEqual(2, _game.TimeMachine.GetState().GetSubList().Count);
            Assert.AreEqual(outpostOneInitial - 1, outpost1.GetComponent<DrillerCarrier>().GetDrillerCount());
            Assert.AreEqual(outpostTwoInitial - 1, outpost2.GetComponent<DrillerCarrier>().GetDrillerCount());
        }

        [TestMethod]
        public void SubsArriveAfterLaunch()
        {
            Outpost outpost1 = new Generator("0",new RftVector(new Rft(300, 300), 0, 0), _game.TimeMachine);
            Outpost outpost2 = new Generator("1",new RftVector(new Rft(300, 300), 0, 10), _game.TimeMachine);
            outpost1.GetComponent<DrillerCarrier>().SetDrillerCount(10);
            outpost2.GetComponent<DrillerCarrier>().SetDrillerCount(5);
            outpost1.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[0]);
            outpost2.GetComponent<DrillerCarrier>().SetOwner(_game.TimeMachine.GetState().GetPlayers()[1]);
            int outpostOneInitial = outpost1.GetComponent<DrillerCarrier>().GetDrillerCount();
            int outpostTwoInitial = outpost2.GetComponent<DrillerCarrier>().GetDrillerCount();

            _game.TimeMachine.GetState().GetOutposts().Add(outpost1);
            _game.TimeMachine.GetState().GetOutposts().Add(outpost2);

            LaunchEvent launch1 = new LaunchEvent(new GameRoomEvent()
            {
                GameEventData = new GameEventData()
                {
                    OccursAtTick = 1,
                    EventDataType = EventDataType.LaunchEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
                    {
                        DestinationId = outpost2.GetComponent<IdentityManager>().GetId(),
                        DrillerCount = 10,
                        SourceId = outpost1.GetComponent<IdentityManager>().GetId(),
                    }),
                },
                Id = "a",
                IssuedBy = _game.TimeMachine.GetState().GetPlayers()[0].PlayerInstance
            });
            Assert.AreEqual(true, launch1.ForwardAction(_game.TimeMachine));

            // Ensure the sub was launched, outpost lost drillers, etc.
            Assert.AreEqual(1, _game.TimeMachine.GetState().GetSubList().Count);
            Assert.AreEqual(outpostOneInitial - 10, outpost1.GetComponent<DrillerCarrier>().GetDrillerCount());

            // Go to the combat.
            var combatHappened = false;
            _game.TimeMachine.GetState().GetSubList()[0].GetComponent<PositionManager>().OnRegisterCombatEffects += (PositionManager, postCombatEvent) =>
            {
                combatHappened = true;
            };

            while (!combatHappened)
            {
                _game.TimeMachine.Advance(1);
            }

            Assert.AreEqual(0, _game.TimeMachine.GetState().GetSubList().Count);
            Assert.AreEqual(outpost1.GetComponent<DrillerCarrier>().GetOwner(), outpost2.GetComponent<DrillerCarrier>().GetOwner());

            // Awkwarddd the outpost generates some shields in the process of the sub travelling.
            // Delta of 1 for the 1 shield that got generated.
            var shieldsGenerated = 1;
            Assert.AreEqual(Math.Abs((outpostTwoInitial + shieldsGenerated) - outpostOneInitial), outpost2.GetComponent<DrillerCarrier>().GetDrillerCount());
        }
    }
}