public Beam(TankOperation operation, Grid grid, SignalWeights weights) { StartAction = operation.GetAction(); EvalState startingState = new EvalState(operation.GetAction(), grid); bestStates[0] = operation.GetScore(startingState, weights); }
public bool Back(int pixels) { this.amount = pixels; this.action = TankAction.Back; this.autoReset.WaitOne(); return lastActionSuccess; }
public TestTankClient(DynObject startResponse, TankAction expectedAction, DynObject takeActionResponse = null) { this.expectedAction = expectedAction; this.startResponse = startResponse; if (takeActionResponse == null) { takeActionResponse = DynObject.Parse(@"{ 'status': 'won', 'health': 200, 'energy': 10, 'orientation': 'north', 'grid': '________________________ ___W_____WWWWWWWW_______ ___W_W__________________ ___W_W_______B__________ ___W_W__________________ ___W_W__________________ _WWWWWWWWW___L____O_____ _____W__________________ _____W_WWWWW____________ _________WWWWWWWW_______ ________________________ ___________WWWW_________ __X_____________________ ________________________ ____WWW_________________ ________________________' }"); } this.takeActionResponse = takeActionResponse; }
public void DoBeforeUpdatingTheState( int currentTick, DateTime nextTickTimeOnServer, TimeSpan timeUntilNextTick, DateTime localTimeBeforeGetStatusCall, DateTime localTimeAfterGetStatusCall) { AllMobileStatesAccountedFor = new bool[Constants.MOBILE_ELEMENT_COUNT]; TankActionsTaken = new TankAction[Constants.TANK_COUNT]; for (int i = 0; i < TankActionsTaken.Length; i++) { TankActionsTaken[i] = TankAction.NONE; } PrevGameState = Game.Current.CurrentTurn.GameState; NewGameState = PrevGameState.Clone(); NewGameState.Tick = currentTick; NewGameState.Outcome = Outcome.InProgress; // TODO: Ideally the current turn should be updated as the very last step, // to prevent race conditions in scenarios where CurrentTurn is accessed // from another thread before the game state is fully updated: UpdateCurrentTurn(currentTick, nextTickTimeOnServer, timeUntilNextTick, localTimeBeforeGetStatusCall, localTimeAfterGetStatusCall); }
public void UpdateTankActionSituation(TankSituation tankSituation, TankAction tankAction, GameState newGameState) { TankAction[] tankActions = new TankAction[] { TankAction.NONE, TankAction.NONE, TankAction.NONE, TankAction.NONE }; tankActions[tankSituation.Tank.Index] = tankAction; List <Point> wallsRemoved = new List <Point>(); MutableGameStateEngine.ApplyAllActions(newGameState as MutableGameState, tankActions, wallsRemoved); bool isAdjacentWallRemoved = false; if (!tankSituation.TankState.IsActive) { IsValid = (TankAction == TankAction.NONE); return; } else { IsValid = true; } if (tankAction == TankAction.FIRE) { Direction movementDir = tankSituation.TankState.Dir; TankLocation tankLoc = Game.Current.Turns[newGameState.Tick].CalculationCache.TankLocationMatrix[tankSituation.TankState.Pos]; Point adjacentWallPoint = tankLoc.OutsideEdgesByDirection[(int)movementDir].CentreCell.Position; isAdjacentWallRemoved = wallsRemoved.Any( wallPoint => wallPoint == adjacentWallPoint ); } NewGameState = newGameState; WallsRemoved = wallsRemoved.ToArray(); IsAdjacentWallRemoved = isAdjacentWallRemoved; NewTankState = NewGameState.GetMobileState(TankSituation.Tank.Index); }
public override void ChooseMovesAsP(MoveResult moveResult) { Move move = moveResult.Move; LogDebugMessage("*** PROTAGONIST (P = {0}) ***", move.p); LogDebugMessage("Slack: {0}", moveResult.Slack); double valueOfMove = ScenarioValueFunctions.ClearRunAtBaseScenarioValueFunction.Evaluate(moveResult.Slack); LogDebugMessage("Value of move: {0}", valueOfMove); // Attack the enemy base: LogDebugMessage("Tank number: {0}", move.i); TankActionRecommendation recommendation = moveResult.GetRecommendedTankActionsByPlayerAndTankNumber(move.p, move.i); if (recommendation.IsAMoveRecommended) { TankSituation tankSituation = GameSituation.GetTankSituationByPlayerAndTankNumber(move.p, move.i); TankAction recommendedTankAction = recommendation.RecommendedTankAction; LogDebugMessage("Recommended tank action: {0}", recommendedTankAction); tankSituation.AdjustTankActionValue(recommendedTankAction, valueOfMove); } else { LogDebugMessage("No moves recommended"); } }
public dynamic TakeAction(TankAction move) { Dictionary<string, string> headers = new Dictionary<string, string>(); headers.Add("X-Sm-Playerid", PlayerId); return client.GetJsonResponse("/game/" + GameId + "/" + move.ToString().ToLower(), "POST", "", headers); }
public override MoveResult EvaluateLeafNodeMove(Move move) { MobileState tankState_i = GetTankState_i(move); MobileState tankState_j = GetTankState_j(move); // Both tanks must be alive: if (!(tankState_i.IsActive && tankState_j.IsActive)) { return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Invalid }); } TankSituation tankSit_i = GetTankSituation(move.p, move.i); TankSituation tankSit_j = GetTankSituation(move.pBar, move.j); int ticksUntilFriendlyTankCanFireAgain = tankSit_i.ExpectedNextTickWhenTankCanFireAgain - GameState.Tick; int ticksUntilEnemyTankCanFireAgain = tankSit_j.ExpectedNextTickWhenTankCanFireAgain - GameState.Tick; if (ticksUntilEnemyTankCanFireAgain <= 0 || ticksUntilFriendlyTankCanFireAgain > 0) { return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Invalid }); } int attackDistance = GetAttackDistanceFromTankToTank(move.p, move.i, move.j); if (attackDistance - ticksUntilEnemyTankCanFireAgain > 5) { return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Invalid }); } foreach (TankActionSituation tankActSit in tankSit_i.TankActionSituationsPerTankAction) { int A_p_i = GetAttackDistanceFromHypotheticalTankStateToTank( tankActSit.NewTankState, move.pBar, move.j, TankHelper.EdgeOffsets); int slack = A_p_i - ticksUntilEnemyTankCanFireAgain; double attackValue = ScenarioValueFunctions.AttackDisarmedEnemyTankSlackUntilRearmedFunction.Evaluate(slack); tankActSit.Value += attackValue; } // Convert a good attacking position into killing the enemy tank, by weighting the attacking action more highly: TankAction[] attackActions = GetTankActionsFromTankToAttackTank(move.p, move.i, move.j); if (attackActions.Length > 0) { TankAction attackAction = attackActions[0]; double attackActionValue = ScenarioValueFunctions.AttackDisarmedEnemyTankAttackActionFunction.Evaluate(attackDistance); tankSit_i.TankActionSituationsPerTankAction[(int)attackAction].Value += attackActionValue; } return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Possible }); }
public TankAction GetBestTankAction() { TankAction bestAction = TankAction.NONE; if (IsTankActionDetermined) { bestAction = ChosenTankAction; } else { double bestValue = double.NegativeInfinity; foreach (TankAction tankAction in TankHelper.TankActions) { TankActionSituation tankActSit = TankActionSituationsPerTankAction[(int)tankAction]; if (tankActSit.IsValid) { double actionValue = tankActSit.Value; if (actionValue > bestValue) { bestValue = actionValue; bestAction = tankAction; } } } } return(bestAction); }
public static TankAction[] GetTankActionsOnShortestPath( DirectionalMatrix <DistanceCalculation> distances, Direction dir, int x, int y) { DistanceCalculation distanceCalc = distances[dir, x, y]; if (distanceCalc.Distance == Constants.UNREACHABLE_DISTANCE) { return(new TankAction[0]); } TankAction[] tankActions = new TankAction[distanceCalc.Distance]; int index = distanceCalc.Distance; Node node = new Node(ActionType.Moving, dir, x, y); while (index != 0) { index--; tankActions[index] = node.Dir.ToTankAction(); node = distanceCalc.AdjacentNode; if (node.ActionType == ActionType.Firing) { index--; tankActions[index] = TankAction.FIRE; node = new Node(ActionType.Moving, node.Dir, node.X, node.Y); } distanceCalc = distances[node.Dir, node.X, node.Y]; } return(tankActions); }
public override void ChooseMovesAsPBar(MoveResult moveResult) { Move move = moveResult.Move; LogDebugMessage("*** ANTAGONIST (PBar = {0}) ***", move.pBar); LogDebugMessage("Slack: {0}", moveResult.Slack); double valueOfMove = ScenarioValueFunctions.ClearRunAtBaseScenarioValueFunction.Evaluate(moveResult.Slack); LogDebugMessage("Value of move: {0}", valueOfMove); // Defend against an enemy attack on your base: for (int tankNumber = 0; tankNumber < Constants.TANKS_PER_PLAYER; tankNumber++) { LogDebugMessage("Tank number: {0}", tankNumber); TankActionRecommendation recommendation = moveResult.GetRecommendedTankActionsByPlayerAndTankNumber(move.pBar, tankNumber); if (recommendation.IsAMoveRecommended) { TankSituation tankSituation = GameSituation.GetTankSituationByPlayerAndTankNumber(move.pBar, tankNumber); TankAction recommendedTankAction = recommendation.RecommendedTankAction; LogDebugMessage("Recommended tank action: {0}", recommendedTankAction); tankSituation.AdjustTankActionValue(recommendedTankAction, valueOfMove); } else { LogDebugMessage("No moves recommended"); } } }
public dynamic TakeAction(TankAction move) { Dictionary <string, string> headers = new Dictionary <string, string>(); headers.Add("X-Sm-Playerid", PlayerId); return(client.GetJsonResponse("/game/" + GameId + "/" + move.ToString().ToLower(), "POST", "", headers)); }
protected TankActionSet() { Actions = new TankAction[Constants.TANKS_PER_PLAYER]; for (int i = 0; i < Constants.TANKS_PER_PLAYER; i++) { Actions[i] = TankAction.NONE; } }
public dynamic TakeAction(TankAction move) { if ((move & expectedAction) == 0) { throw new Exception("Got: " + move + ", expected: " + expectedAction); } return(takeActionResponse); }
public EvalState(TankAction action, EvalState previousState, int score, Grid grid) : this(action, grid) { if (previousState.Evaluated) { this.previousState = previousState; } this.Score = previousState.Score + score; }
// TODO: honour the timeoutInMilliseconds setting public bool TrySetActions(int playerIndex, TankAction tankAction1, TankAction tankAction2, ICommunicatorCallback callback, int timeoutInMilliseconds) { ChallengeClient client = new ChallengeClient(EndPointConfigurationName, Url); client.Open(); try { try { client.setActions(tankAction1.Convert(), tankAction2.Convert()); return(true); } catch (FaultException <EndOfGameException> endOfGameFault) { LogDebugError(endOfGameFault, endOfGameFault.Message); callback.UpdateGameOutcomeToLoseDueToError(playerIndex, endOfGameFault.Message); return(false); } catch (FaultException <NoBlameException> noBlameFault) { LogDebugError(noBlameFault, noBlameFault.Message); callback.UpdateGameOutcomeDueToNoBlameCrash(noBlameFault.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } catch (EndpointNotFoundException endpointException) { LogDebugError(endpointException, endpointException.Message); callback.UpdateGameOutcomeDueToServerUnavailable(endpointException.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } catch (CommunicationException commsException) { LogDebugError(commsException, commsException.Message); callback.UpdateGameOutcomeDueToServerUnavailable(commsException.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } } finally { client.Close(); } }
public static TankAction[] ConvertNodesToTankActions(Node[] nodes) { TankAction[] tankActions = new TankAction[nodes.Length]; for (int i = 0; i < nodes.Length; i++) { Node node = nodes[i]; TankAction tankAction = node.ActionType == ActionType.Firing ? TankAction.FIRE : node.Dir.ToTankAction(); tankActions[i] = tankAction; } return(tankActions); }
public bool TrySetTankActions(TankActionSet actionSet, int timeoutInMilliseconds) { if (actionSet == null) { return(true); } if (actionSet.Tick != Game.Current.CurrentTurn.Tick) { LogDebugMessage("Tank actions not submitted as tick {0} is in the past", actionSet.Tick); return(false); } int playerIndex = actionSet.PlayerIndex; GameState currentGameState = Game.Current.CurrentTurn.GameState; int numberAlive = 0; int tankId = -1; TankAction tankAction = TankAction.NONE; int tankNumber = -1; for (int t = 0; t < Constants.TANKS_PER_PLAYER; t++) { Tank tank = Game.Current.Players[actionSet.PlayerIndex].Tanks[t]; MobileState tankState = currentGameState.GetMobileState(tank.Index); if (tankState.IsActive) { numberAlive++; tankId = tank.Id; tankAction = actionSet.Actions[t]; tankNumber = tank.Number; } } LogDebugMessage("Sending tank actions for player {0}", Solver.YourPlayerIndex); if (numberAlive == 1) { LogDebugMessage(" Tank {0} action {1} (tank id: {2})", tankNumber, tankAction, tankId); return(Communicator.TrySetAction(playerIndex, tankId, tankAction, CommunicatorCallback, timeoutInMilliseconds)); } else if (numberAlive == 2) { TankAction tankAction1 = actionSet.Actions[0]; TankAction tankAction2 = actionSet.Actions[1]; LogDebugMessage(" Tank 0 action {0}", tankAction1); LogDebugMessage(" Tank 1 action {0}", tankAction2); return(Communicator.TrySetActions(playerIndex, tankAction1, tankAction2, CommunicatorCallback, timeoutInMilliseconds)); } else { return(true); } }
public TankAction GetNextAction(TankAction? previousAction) { if (TankAPI.CurrentState.TargetInSight) return TankAction.FireCannon; if (TankAPI.CurrentState[Direction.Front] > 1) { return TankAction.MoveForward; } return AvoidDeadEnd(); }
public TankActionSet GenerateTankActions(int yourPlayerIndex, int tick) { TankActionSet tankActionSet = new TankActionSet(yourPlayerIndex, tick); foreach (Tank tank in Game.Current.Players[yourPlayerIndex].Tanks) { TankSituation tankSituation = TankSituationsByTankIndex[tank.Index]; TankAction bestAction = tankSituation.GetBestTankAction(); tankActionSet.Actions[tank.Number] = bestAction; } return(tankActionSet); }
private Direction?DetectCloseIn(TankAction previousAction, TankState previousState, TankState currentState) { if (previousAction == TankAction.TurnLeft || previousAction == TankAction.TurnRight) { return(null); } var closeIn = default(Direction?); var right_closeIn = false; var left_closeIn = false; if (currentState[Direction.Left] < previousState[Direction.Left]) { left_closeIn = true; } if (currentState[Direction.Right] < previousState[Direction.Right]) { right_closeIn = true; } if (right_closeIn && left_closeIn) { if (currentState[Direction.Left] - previousState[Direction.Left] <= currentState[Direction.Right] - previousState[Direction.Right]) { closeIn = Direction.Left; } else { closeIn = Direction.Right; } } else if (left_closeIn) { closeIn = Direction.Left; } else if (right_closeIn) { closeIn = Direction.Right; } if (closeIn.HasValue && currentState[closeIn.Value] == 1) { closeIn = null; } return(closeIn); }
private void LogActionsTaken() { for (int t = 0; t < Constants.TANK_COUNT; t++) { MobileState tankState = NewGameState.GetMobileState(t); if (tankState.IsActive) { Tank tank = Game.Current.Elements[t] as Tank; TankAction actionTaken = TankActionsTaken[t]; LogDebugMessage("Player {0} tank {1} took action {2} and is now at {3}", tank.PlayerNumber, tank.Number, actionTaken, tankState.Pos); } } DebugHelper.WriteLine(); }
public static Direction ToDirection(this TankAction action, Direction currentDirection = Direction.NONE) { switch (action) { case TankAction.DOWN: case TankAction.LEFT: case TankAction.RIGHT: case TankAction.UP: return((Direction)action); default: // case TankAction.NONE: // case TankAction.FIRE: return(currentDirection); } }
public void ChooseTankAction(TankAction tankAction) { if (IsTankActionDetermined) { if (tankAction != ChosenTankAction) { throw new InvalidOperationException( string.Format( "The tank with index {0}) already has a chosen action of {1}. This can't be changed to {2}.", Tank.Index, ChosenTankAction, tankAction)); } return; } ChosenTankAction = tankAction; IsTankActionDetermined = true; }
public override MoveResult EvaluateLeafNodeMove(Move move) { MobileState tankState_i = GetTankState_i(move); TankSituation tankSit_i = GetTankSituation(move.p, move.i); if (tankSit_i.IsLockedDown || !tankState_i.IsActive) { return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Invalid }); } foreach (TankActionSituation tankActSit in tankSit_i.TankActionSituationsPerTankAction) { MobileState newTankState = tankActSit.NewTankState; int attackDistToEnemyBase = GetAttackDistanceToEnemyBaseFromTankState(YourPlayerIndex, ref newTankState); if (tankActSit.TankAction == TankAction.FIRE && tankActSit.IsAdjacentWallRemoved) { Point adjacentPos = tankActSit.NewTankState.Pos + tankActSit.NewTankState.Dir.GetOffset(); MobileState adjacentState = new MobileState(adjacentPos, tankActSit.NewTankState.Dir, isActive: true); int attackDistToEnemyBase2 = GetAttackDistanceToEnemyBaseFromTankState(YourPlayerIndex, ref adjacentState) + 1; if (attackDistToEnemyBase2 < attackDistToEnemyBase) { attackDistToEnemyBase = attackDistToEnemyBase2; } } double value = ScenarioValueFunctions.AttackEnemyBaseFunction.Evaluate(attackDistToEnemyBase); tankActSit.Value += value; } // Convert a good position into killing the enemy base, by weighting the attacking action more highly: int attackDistance = GetAttackDistanceToEnemyBaseFromTankState(move.i, ref tankState_i); TankAction[] attackActions = GetActionsToAttackEnemyBase(move.p, move.i); if (attackActions.Length > 0) { TankAction attackAction = attackActions[0]; double attackActionValue = ScenarioValueFunctions.AttackEnemyBaseAttackActionFunction.Evaluate(attackDistance); tankSit_i.TankActionSituationsPerTankAction[(int)attackAction].Value += attackActionValue; } return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Possible }); }
public override MoveResult EvaluateLeafNodeMove(Move move) { TankSituation tankSituation = GetTankSituation(move.p, move.i); int ticksUntil_p_i_CanFireAgain = tankSituation.ExpectedNextTickWhenTankCanFireAgain - GameState.Tick; int worstSlack = -Constants.UNREACHABLE_DISTANCE; TankAction tankActionToAddressWorstSlack = TankAction.NONE; bool isScenarioApplicable = false; foreach (BulletSituation bulletSituation in GameSituation.BulletSituationsByTankIndex) { if (bulletSituation == null) { continue; } EvaluateBulletSituation(move, tankSituation, bulletSituation, ticksUntil_p_i_CanFireAgain, ref worstSlack, ref tankActionToAddressWorstSlack, ref isScenarioApplicable); } if (isScenarioApplicable) { MoveResult moveResult = new MoveResult(move) { Slack = worstSlack, EvaluationOutcome = worstSlack < -10 ? ScenarioEvaluationOutcome.Possible : (worstSlack <= 0 ? ScenarioEvaluationOutcome.Close : ScenarioEvaluationOutcome.Current ) }; moveResult.RecommendedTankActionsByTankIndex[tankSituation.Tank.Index] = new TankActionRecommendation { IsAMoveRecommended = true, RecommendedTankAction = tankActionToAddressWorstSlack }; return(moveResult); } else { return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Invalid }); } }
public override MoveResult EvaluateLeafNodeMove(Move move) { MobileState tankState_i = GetTankState_i(move); MobileState tankState_j = GetTankState_j(move); // Both tanks must be alive: if (!(tankState_i.IsActive && tankState_j.IsActive)) { return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Invalid }); } TankSituation tankSit_i = GetTankSituation(move.p, move.i); // Weight for distance to attack enemy over the long haul versus having the upper hand in the encounter in the short term: foreach (TankActionSituation tankActSit in tankSit_i.TankActionSituationsPerTankAction) { int A_p_i = GetAttackDistanceFromHypotheticalTankStateToTank( tankActSit.NewTankState, move.pBar, move.j, TankHelper.EdgeOffsets); int A_pBar_j = GetAttackDistanceFromTankToHypotheticalTankAtPoint( move.pBar, move.j, tankActSit.NewTankState.Pos, TankHelper.EdgeOffsets); int attackDiffSlack = A_p_i - A_pBar_j; double attackValue = ScenarioValueFunctions.GrappleWithEnemyTankAttackFunction.Evaluate(A_p_i); double grappleValue = ScenarioValueFunctions.GrappleWithEnemyTankAttackDiffFunction.Evaluate(attackDiffSlack); tankActSit.Value += attackValue + grappleValue; } // Convert a good attacking position into killing the enemy tank, by weighting the attacking action more highly: int attackDistance = GetAttackDistanceFromTankToTank(move.p, move.i, move.j); TankAction[] attackActions = GetTankActionsFromTankToAttackTank(move.p, move.i, move.j); if (attackActions.Length > 0) { TankAction attackAction = attackActions[0]; double attackActionValue = ScenarioValueFunctions.GrappleWithEnemyTankAttackActionFunction.Evaluate(attackDistance); tankSit_i.TankActionSituationsPerTankAction[(int)attackAction].Value += attackActionValue; } return(new MoveResult(move) { EvaluationOutcome = ScenarioEvaluationOutcome.Possible }); }
public void Run(SignalWeights weights) { dynamic joinResponse = client.Start(); turnTimeout = (joinResponse.config.turn_timeout / 1000) - 5000; Grid grid = new Grid(); Status status = ParseStatus(joinResponse, grid); while (status == Status.Running) { numberOfTurns++; TankAction action = GetBestAction(grid, weights); dynamic moveResponse = client.TakeAction(action); status = ParseStatus(moveResponse, grid); } }
public override void ChooseMovesAsP(MoveResult moveResult) { Move move = moveResult.Move; MobileState tankState_j = GetTankState_j(move); TankAction[] attackActions = GetTankActionsFromTankToAttackTankAtPointAlongDirectionOfMovement( move.p, move.i, tankState_j.Pos, move.dir1, TankHelper.EdgeOffsets, keepMovingCloserOnFiringLastBullet: false); if (attackActions.Length > 0) { int attackDistance = GetAttackDistanceFromTankToTankAtPointAlongDirectionOfMovement( move.p, move.i, tankState_j.Pos, move.dir1, TankHelper.EdgeOffsets); TankAction attackAction = attackActions[0]; double attackActionValue = ScenarioValueFunctions.AttackLockedDownEnemyTankFunction.Evaluate(attackDistance); TankSituation tankSit_i = GetTankSituation(move.p, move.i); tankSit_i.TankActionSituationsPerTankAction[(int)attackAction].Value += attackActionValue; } }
/// <summary> /// /// </summary> /// <returns></returns> public TankAction GetNextAction(TankAction? previousAction) { var nextAction = default(TankAction); if (previousAction.HasValue && previousAction.Value == TankAction.TryToShoot && TankAPI.CurrentState.TargetInSight) { nextAction = TankAction.TryToShoot; Console.WriteLine("--DEBUG: ShootTurnShoot TryShoot AGAIN!"); } else { nextAction = _queue.Dequeue(); } Console.WriteLine("--DEBUG: ShootTurnShoot Action: {0}", nextAction); return nextAction; }
private Direction? DetectCloseIn(TankAction previousAction, TankState previousState, TankState currentState) { if (previousAction == TankAction.TurnLeft || previousAction == TankAction.TurnRight) { return null; } var closeIn = default(Direction?); var right_closeIn = false; var left_closeIn = false; if (currentState[Direction.Left] < previousState[Direction.Left]) left_closeIn = true; if (currentState[Direction.Right] < previousState[Direction.Right]) right_closeIn = true; if (right_closeIn && left_closeIn) { if (currentState[Direction.Left] - previousState[Direction.Left] <= currentState[Direction.Right] - previousState[Direction.Right]) { closeIn = Direction.Left; } else { closeIn = Direction.Right; } } else if (left_closeIn) { closeIn = Direction.Left; } else if (right_closeIn) { closeIn = Direction.Right; } if (closeIn.HasValue && currentState[closeIn.Value] == 1) closeIn = null; return closeIn; }
public void UpdateTankState(int unitId, TankAction tankAction, Point newPos, Direction newDir, bool isActive) { bool tankFound = false; for (int t = 0; t < Constants.TANK_COUNT; t++) { Tank tank = Game.Current.Elements[t] as Tank; if (tank.Id == unitId) { MobileState newMobileState = new MobileState(newPos, newDir, isActive); NewGameState.SetMobileState(t, ref newMobileState); TankActionsTaken[tank.Index] = tankAction; tankFound = true; AllMobileStatesAccountedFor[tank.Index] = true; break; } } /* TODO: Else find a likely matching tank in the previous game state based on position and direction: */ #if DEBUG if (!tankFound) { LogDebugMessage("ERROR! No existing tank could be found with id {0} at position ({1}, {2})", unitId, newPos.X, newPos.Y); #if THROW_HARNESS_ERRORS throw new InvalidOperationException( String.Format( "No existing tank could be found with id {0} at position ({1}, {2})", unitId, newPos.X, newPos.Y) ); #endif } #endif }
private static int InitializePlayersAndUnitsAndGetYourPlayerIndex(game wsGame, ICommunicatorCallback callback) { int yourPlayerIndex = -1; // To keep the compiler happy for (int playerIndex = 0; playerIndex < wsGame.players.Length; playerIndex++) { player wsPlayer = wsGame.players[playerIndex]; string playerName = wsPlayer.name; bool isYou = false; if (playerName == wsGame.playerName) { yourPlayerIndex = playerIndex; isYou = true; } Point basePos = new Point((short)[email protected], (short)[email protected]); callback.InitializePlayer(playerIndex, playerName, basePos, isYou); // Set up the tanks: for (int tankNumber = 0; tankNumber < wsPlayer.units.Length; tankNumber++) { unit tankUnit = wsPlayer.units[tankNumber]; int unitId = tankUnit.id; Point initialTankPosition = new Point((short)tankUnit.x, (short)tankUnit.y); Direction initialTankDirection = tankUnit.directionSpecified ? tankUnit.direction.Convert() : Direction.NONE; TankAction initialTankAction = tankUnit.actionSpecified ? tankUnit.action.Convert() : TankAction.NONE; callback.InitializeTank(playerIndex, tankNumber, unitId, ref initialTankPosition, initialTankDirection, initialTankAction); } } return(yourPlayerIndex); }
public static action Convert(this TankAction tankAction) { switch (tankAction) { case TankAction.DOWN: return(global::action.DOWN); case TankAction.FIRE: return(global::action.FIRE); case TankAction.LEFT: return(global::action.LEFT); case TankAction.RIGHT: return(global::action.RIGHT); case TankAction.UP: return(global::action.UP); default: // case TankAction.NONE return(global::action.NONE); } }
public TankController(Tank tank) { this.action = TankAction.None; this.Tank = tank; this.autoReset = new AutoResetEvent(false); }
public void TurnRight(int degrees) { this.amount = degrees; this.action = TankAction.Right; this.autoReset.WaitOne(); }
public void TurnGunLeft(int degrees) { this.amount = degrees; this.action = TankAction.TurretLeft; this.autoReset.WaitOne(); }
public static void PerformAction(TankAction action) { var apiAction = default(System.Action); switch (action) { case TankAction.FireCannon: apiAction = API.FireCannon; break; case TankAction.MoveForward: apiAction = API.MoveForward; _currentPosition = _currentPosition + CompassMapping.GetDirectionSign(_currentDirection) * CompassMapping.GetDirectionOffset(_currentDirection, (uint) 1); break; case TankAction.MoveBackward: apiAction = API.MoveBackward; var oppsiteDirection = CompassMapping.GetOppositeDirection(_currentDirection); _currentPosition = _currentPosition + CompassMapping.GetDirectionSign(oppsiteDirection) * CompassMapping.GetDirectionOffset(oppsiteDirection, (uint) 1); break; case TankAction.TurnLeft: apiAction = API.TurnLeft; _currentDirection = CompassMapping.GetNewDirection( _currentDirection, Compass.West); break; case TankAction.TurnRight: apiAction = API.TurnRight; _currentDirection = CompassMapping.GetNewDirection( _currentDirection, Compass.East); break; case TankAction.TryToShoot: apiAction = () => { if (CurrentState.TargetInSight) API.FireCannon(); }; break; default: apiAction = null; break; } if (apiAction == null) { throw new ApplicationException(string.Format("Unknown TankAction: {0}", (int) action)); } TankAPI.ConsumeTurn(apiAction); }
private void EvaluateBulletSituation(Move move, TankSituation tankSituation, BulletSituation bulletSituation, int ticksUntil_p_i_CanFireAgain, ref int worstSlack, ref TankAction tankActionToAddressWorstSlack, ref bool isScenarioApplicable) { bool isScenarioApplicableForThisBulletSituation = false; int bestSlackForThisBulletSituation = Constants.UNREACHABLE_DISTANCE; TankAction bestTankActionForThisBulletSituation = TankAction.NONE; foreach (BulletCalculationByTick bulletCalc in bulletSituation.BulletCalculationsByTick) { if (!bulletCalc.AreTanksAtRisk) { continue; } int ticksToEscape = bulletCalc.Tick - GameState.Tick; if (ticksToEscape < 0) { continue; } // Are you in the firing line: if (bulletCalc.TankCentrePointsThatDie.ContainsPoint(tankSituation.TankState.Pos)) { List <BulletSurvivalTactic> bulletTactics = new List <BulletSurvivalTactic>(); isScenarioApplicableForThisBulletSituation = true; // Suppose the bullet just misses the tank on turn n, with t ticks to escape... int closestEscapeTick = ticksToEscape * 2 / 3; // 2t - n + 1 = 2n + 1 so 3n = 2t int furthestEscapeTick = 2 * ticksToEscape + 1; // 2t + n + 1 = 2n so n = 2t + 1 for (int tk = closestEscapeTick; tk <= furthestEscapeTick; tk++) { if (tk >= bulletSituation.BulletCalculationsByTick.Length) { break; } BulletCalculationByTick bulletCalc_tk = bulletSituation.BulletCalculationsByTick[tk]; if (!bulletCalc_tk.AreTanksAtRisk) { break; } ticksToEscape = bulletCalc_tk.Tick - GameState.Tick; // Fire at the bullet: foreach (MobileState headOnState in bulletCalc_tk.ClosestTankStatesThatCanShootBulletHeadOn) { // Move into position to confront the bullet: AddBulletSurvivalTactic(move, ticksUntil_p_i_CanFireAgain, ticksToEscape, bulletTactics, headOnState, bulletSituation.TickOffsetWhenTankCanFireAgain, isConfrontingBullet: true); } // Other moves to dodge the bullet: foreach (Point survivalPoint in bulletCalc_tk.ClosestTankCentrePointsThatSurviveClockwise) { Direction dir = bulletSituation.BulletMovementDir.Clockwise(); AddBulletSurvivalTactic(move, ticksUntil_p_i_CanFireAgain, ticksToEscape, bulletTactics, survivalPoint, dir, bulletSituation.TickOffsetWhenTankCanFireAgain, isConfrontingBullet: false); } foreach (Point survivalPoint in bulletCalc_tk.ClosestTankCentrePointsThatSurviveAntiClockwise) { Direction dir = bulletSituation.BulletMovementDir.AntiClockwise(); AddBulletSurvivalTactic(move, ticksUntil_p_i_CanFireAgain, ticksToEscape, bulletTactics, survivalPoint, dir, bulletSituation.TickOffsetWhenTankCanFireAgain, isConfrontingBullet: false); } } var bulletTacticsByTankAction = bulletTactics.GroupBy(tactic => tactic.InitialTankAction); foreach (var grouping in bulletTacticsByTankAction) { TankAction tankAction = grouping.Key; BulletSurvivalTactic bestTacticForTankAction = grouping.OrderBy(tactic => tactic.Value).First(); tankSituation.TankActionSituationsPerTankAction[(int)tankAction].Value += bestTacticForTankAction.Value; // Note that this is a combination of the slack value and the disarmament value if (bestTacticForTankAction.Slack < bestSlackForThisBulletSituation) { bestSlackForThisBulletSituation = bestTacticForTankAction.Slack; bestTankActionForThisBulletSituation = tankAction; } } // We've made our escape plans. Don't continue iterating through bullet calculations... break; } // If any of the danger points are adjacent to your current point, // prevent moving into the bullet by add a large negative value to the move, // with the size of the value depending on the slack... foreach (TankActionSituation tankActionSituation in tankSituation.TankActionSituationsPerTankAction) { if (bulletCalc.TankCentrePointsThatDie.ContainsPoint(tankActionSituation.NewTankState.Pos)) { // Calculate the slack values and tank action value adjustment... double value = ScenarioValueFunctions.AvoidWalkingIntoABulletFunction.Evaluate(ticksToEscape); tankActionSituation.Value += value; } } } if (isScenarioApplicableForThisBulletSituation) { if (bestSlackForThisBulletSituation > worstSlack) { worstSlack = bestSlackForThisBulletSituation; tankActionToAddressWorstSlack = bestTankActionForThisBulletSituation; } isScenarioApplicable = true; } }
public dynamic TakeAction(TankAction move) { if ((move & expectedAction) == 0) throw new Exception("Got: " + move + ", expected: " + expectedAction); return takeActionResponse; }
public void Tick(TimeSpan elapsedTime) { lastActionSuccess = true; switch (this.action) { case TankAction.Ahead: case TankAction.Back: var pixelPerMillesecond = TankConfig.PixelPerSecondMovementSpeed / 1000; var pixelMovement = Math.Min(elapsedTime.TotalMilliseconds * pixelPerMillesecond, this.amount); var tankMovementAngle = this.action == TankAction.Ahead ? this.Tank.Angle : this.Tank.Angle - (float)Math.PI; var newAngle = this.Tank.Position.Move(tankMovementAngle, pixelMovement); if (this.Tank.Position.X < TankConfig.ArenaEndX && this.Tank.Position.X > TankConfig.ArenaStartX && this.Tank.Position.Y < TankConfig.ArenaEndY && this.Tank.Position.Y > TankConfig.ArenaStartY) { this.Tank.Position = newAngle; this.amount -= pixelMovement; } else { this.lastActionSuccess = false; this.amount = 0; } break; case TankAction.Right: case TankAction.Left: var turnMillisecondRate = (2 * (float)Math.PI) / TankConfig.TankFullTurnTime.TotalMilliseconds; var totalTurnRadian = Math.Min(elapsedTime.TotalMilliseconds * turnMillisecondRate, StaticHelpers.DegreeToRadian(this.amount)); if (this.action == TankAction.Right) { this.Tank.Angle += (float)totalTurnRadian; } else { this.Tank.Angle -= (float)totalTurnRadian; } var totalTurnDegrees = StaticHelpers.RadianToDegree(totalTurnRadian); this.amount -= totalTurnDegrees; break; case TankAction.TurretLeft: case TankAction.TurretRight: var turretTurnturnMillisecondRate = (2 * (float)Math.PI) / TankConfig.TankFullTurnTime.TotalMilliseconds; var totalturretTurnRadian = Math.Min(elapsedTime.TotalMilliseconds * turretTurnturnMillisecondRate, StaticHelpers.DegreeToRadian(this.amount)); if (this.action == TankAction.Right) { this.Tank.TurretAngle += (float)totalturretTurnRadian; } else { this.Tank.TurretAngle -= (float)totalturretTurnRadian; } var totalTurretTurnDegrees = StaticHelpers.RadianToDegree(totalturretTurnRadian); this.amount -= totalTurretTurnDegrees; break; default: this.amount = 0; return; } if (this.amount <= 0) { this.action = TankAction.None; this.autoReset.Set(); } }
public EvalState(TankAction action, Grid grid) { this.Action = action; this.Grid = grid; }