Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added C#, .NET Core compatible starter kit #14

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions starter_kits/C#/Core/Command.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace Halite3.Core
{
public class Command
{
public string CommandValue { get; private set; }

public static Command spawnShip()
{
return new Command("g");
}

public static Command transformShipIntoDropoffSite(EntityId id)
{
return new Command("c " + id.Id);
}

public static Command move(EntityId id, Direction direction)
{
return new Command("m " + id.Id + ' ' + (char)direction);
}

private Command(string command)
{
this.CommandValue = command;
}

public override bool Equals(object other)
{
if (this == other) return true;
if (!(other is Command)) return false;

var otherCommand = other as Command;

return CommandValue.Equals(otherCommand.CommandValue);
}

public override int GetHashCode()
{
return CommandValue.GetHashCode();
}
}
}
63 changes: 63 additions & 0 deletions starter_kits/C#/Core/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Halite3.Core
{
public class Constants
{
/** The maximum amount of halite a ship can carry. */
public static int MAX_HALITE { get; private set; }
/** The cost to build a single ship. */
public static int SHIP_COST { get; private set; }
/** The cost to build a dropoff. */
public static int DROPOFF_COST { get; private set; }
/** The maximum number of turns a game can last. */
public static int MAX_TURNS { get; private set; }
/** 1/EXTRACT_RATIO halite (rounded) is collected from a square per turn. */
public static int EXTRACT_RATIO { get; private set; }
/** 1/MOVE_COST_RATIO halite (rounded) is needed to move off a cell. */
public static int MOVE_COST_RATIO { get; private set; }
/** Whether inspiration is enabled. */
public static bool INSPIRATION_ENABLED { get; private set; }
/** A ship is inspired if at least INSPIRATION_SHIP_COUNT opponent ships are within this Manhattan distance. */
public static int INSPIRATION_RADIUS { get; private set; }
/** A ship is inspired if at least this many opponent ships are within INSPIRATION_RADIUS distance. */
public static int INSPIRATION_SHIP_COUNT { get; private set; }
/** An inspired ship mines 1/X halite from a cell per turn instead. */
public static int INSPIRED_EXTRACT_RATIO { get; private set; }
/** An inspired ship that removes Y halite from a cell collects X*Y additional halite. */
public static double INSPIRED_BONUS_MULTIPLIER { get; private set; }
/** An inspired ship instead spends 1/X% halite to move. */
public static int INSPIRED_MOVE_COST_RATIO { get; private set; }

public static void populateConstants(string stringFromEngine)
{
var temp = stringFromEngine.Replace('{', ' ');
temp = temp.Replace('}', ' ');
temp = temp.Replace('"', ' ');

var tokens = temp.Split(',');

var lookup = tokens.Select(token => {
var split = token.Split(':');
return new { key = split[0].Trim(), value = split[1].Trim() };
}).ToDictionary(token => token.key, token => token.value);

var constantsMap = new Dictionary<string, string>();

SHIP_COST = int.Parse(lookup["NEW_ENTITY_ENERGY_COST"]);
DROPOFF_COST = int.Parse(lookup["DROPOFF_COST"]);
MAX_HALITE = int.Parse(lookup["MAX_ENERGY"]);
MAX_TURNS = int.Parse(lookup["MAX_TURNS"]);
EXTRACT_RATIO = int.Parse(lookup["EXTRACT_RATIO"]);
MOVE_COST_RATIO = int.Parse(lookup["MOVE_COST_RATIO"]);
INSPIRATION_ENABLED = bool.Parse(lookup["INSPIRATION_ENABLED"]);
INSPIRATION_RADIUS = int.Parse(lookup["INSPIRATION_RADIUS"]);
INSPIRATION_SHIP_COUNT = int.Parse(lookup["INSPIRATION_SHIP_COUNT"]);
INSPIRED_EXTRACT_RATIO = int.Parse(lookup["INSPIRED_EXTRACT_RATIO"]);
INSPIRED_BONUS_MULTIPLIER = double.Parse(lookup["INSPIRED_BONUS_MULTIPLIER"]);
INSPIRED_MOVE_COST_RATIO = int.Parse(lookup["INSPIRED_MOVE_COST_RATIO"]);
}
}
}
30 changes: 30 additions & 0 deletions starter_kits/C#/Core/Direction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections;

namespace Halite3.Core
{
public enum Direction
{
NORTH = 'n',
EAST = 'e',
SOUTH = 's',
WEST = 'w',
STILL = 'o'
}

public static class DirectionExtensions
{
public static Direction InvertDirection(this Direction direction)
{
switch (direction)
{
case Direction.NORTH: return Direction.SOUTH;
case Direction.EAST: return Direction.WEST;
case Direction.SOUTH: return Direction.NORTH;
case Direction.WEST: return Direction.EAST;
case Direction.STILL: return Direction.STILL;
default: throw new ArgumentException("Unknown direction " + direction);
}
}
}
}
21 changes: 21 additions & 0 deletions starter_kits/C#/Core/Dropoff.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Halite3.Core
{
public class Dropoff : Entity
{
public Dropoff(PlayerId owner, EntityId id, Position position) :
base(owner, id, position)
{
}

internal static Dropoff _generate(PlayerId playerId)
{
Input input = Input.readInput();

EntityId dropoffId = new EntityId(input.getInt());
int x = input.getInt();
int y = input.getInt();

return new Dropoff(playerId, dropoffId, new Position(x, y));
}
}
}
36 changes: 36 additions & 0 deletions starter_kits/C#/Core/Entity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace Halite3.Core
{
public class Entity
{
public PlayerId Owner { get; private set; }
public EntityId Id { get; private set; }
public Position Position { get; private set; }

public Entity(PlayerId owner, EntityId id, Position position)
{
Owner = owner;
Id = id;
Position = position;
}

public override bool Equals(object other)
{
if (this == other) return true;
if (!(other is Entity)) return false;

var entity = other as Entity;

if (!Owner.Equals(entity.Owner)) return false;
if (!Id.Equals(entity.Id)) return false;
return Position.Equals(entity.Position);
}

public override int GetHashCode()
{
int result = Owner.GetHashCode();
result = 31 * result + Id.GetHashCode();
result = 31 * result + Position.GetHashCode();
return result;
}
}
}
29 changes: 29 additions & 0 deletions starter_kits/C#/Core/EntityId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace Halite3.Core
{
public class EntityId
{
public static EntityId NONE = new EntityId(-1);

public int Id { get; private set; }

public EntityId(int id)
{
Id = id;
}

public override bool Equals(object other)
{
if (this == other) return true;
if (!(other is EntityId)) return false;

var entityId = other as EntityId;

return Id == entityId.Id;
}

public override int GetHashCode()
{
return Id;
}
}
}
86 changes: 86 additions & 0 deletions starter_kits/C#/Core/Game.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;

namespace Halite3.Core
{
public class Game
{
public int TurnNumber { get; private set; }
public PlayerId MyId { get; private set; }
public Dictionary<int, Player> Players { get; private set; }
public Player Me { get; private set; }
public GameMap GameMap { get; private set; }

public Game()
{
Players = new Dictionary<int, Player>();

Constants.populateConstants(Input.ReadLine());

Input input = Input.readInput();
int numPlayers = input.getInt();
MyId = new PlayerId(input.getInt());

Log.Info("My Id: " + MyId.Id);

for (var i = 0; i < numPlayers; ++i)
{
var player = Player._generate();
Players.Add(player.Id.Id, player);
}

Me = Players[MyId.Id];
GameMap = GameMap._generate();
}

public void Ready(string name)
{
Console.WriteLine(name);
}

public void UpdateFrame()
{
TurnNumber = Input.readInput().getInt();
Log.Info("=============== TURN " + TurnNumber + " ================");

for (int i = 0; i < Players.Count; ++i)
{
Input input = Input.readInput();

PlayerId currentPlayerId = new PlayerId(input.getInt());
int numShips = input.getInt();
int numDropoffs = input.getInt();
int halite = input.getInt();

Players[currentPlayerId.Id]._update(numShips, numDropoffs, halite);
}

GameMap._update();

foreach (var player in Players.Values)
{
foreach (var ship in player.Ships.Values)
{
GameMap.At(ship).markUnsafe(ship);
}

GameMap.At(player.Shipyard).Structure = player.Shipyard;

foreach (var dropoff in player.Dropoffs.Values)
{
GameMap.At(dropoff).Structure = dropoff;
}
}
}

public void EndTurn(List<Command> commands)
{
foreach (var command in commands)
{
Console.Write(command.CommandValue);
Console.Write(' ');
}
Console.WriteLine();
}
}
}
Loading