public RobotAction Tick(int robotId, RoundConfig config, GameState state) { RobotState self = state.robots[robotId]; RobotAction action = new RobotAction(); action.targetId = -1; position mine = new position(); position charging_station = new position(); position service_station = new position(); charging_station = getNearestChargingStation(state, self); service_station = getNearestServiceStation(state, self); mine.x = self.X; mine.y = self.Y; HealthExchange(self, config, action, 0.0f, 0.4f, 0.6f); if (mine.x == charging_station.x && mine.y == charging_station.y && (self.attack + self.defence + self.speed) < 0.95 * config.max_health) { return(action); } if (mine.x == service_station.x && mine.y == service_station.y && self.energy < 0.99 * config.max_energy) { return(action); } //или пополняем энергию //MoveTo(charging_station, self, config, action); if (self.energy <= 0.8 * config.max_energy) { HealthExchange(self, config, action, 0.0f, 0.2f, 0.8f); MoveTo(getNearestServiceStation(state, self), self, config, action); return(action); } else { //или пополняем техн. состояние int service_sost = self.attack + self.defence + self.speed; if (service_sost <= 0.9 * config.max_health) { MoveTo(getNearestChargingStation(state, self), self, config, action); //записываем информацию о движении return(action); } else { int attack_range = (int)(config.max_radius) * 10 * self.speed * self.energy / (config.max_energy * config.max_health); HealthExchange(self, config, action, 0.4f, 0.4f, 0.2f); //или ищем цель для удара и защиты int enemy_id = -1; bool under_attack = false; for (int id = 0; id < state.robots.Count; id++) { RobotState rs = state.robots[id]; if (rs.name != self.name) { int enemy_distance_attack = 10 * config.max_radius * rs.speed * rs.energy / config.max_health / config.max_energy; int distance = getDistance(self.X, self.Y, rs.X, rs.Y); if (distance <= enemy_distance_attack && distance <= attack_range) { under_attack = true; enemy_id = id; } } } int target_id = GetNearestTarget(robotId, config, state, true, true); HealthExchange(self, config, action, 0.4f, 0.4f, 0.2f); if (target_id >= 0) { RobotState target = state.robots[target_id]; position target_pos = new position(); target_pos.x = target.X; target_pos.y = target.Y; MoveTo(target_pos, self, config, action); position distance = new position(); distance.x = self.X + action.dX; distance.y = self.Y + action.dY; int dist = getDistance(self.X + action.dX, self.Y + action.dY, target_pos.x, target_pos.y); if (dist <= attack_range) { action.targetId = target_id; } } } } return(action); }
private async void Round_StatusChangedAsync(object sender, CoordinatorRoundStatus status) { try { var round = sender as CoordinatorRound; Money feePerInputs = null; Money feePerOutputs = null; // If success save the coinjoin. if (status == CoordinatorRoundStatus.Succeded) { uint256[] mempoolHashes = null; try { mempoolHashes = await RpcClient.GetRawMempoolAsync().ConfigureAwait(false); } catch (Exception ex) { Logger.LogError(ex); } using (await CoinJoinsLock.LockAsync().ConfigureAwait(false)) { if (mempoolHashes is { }) { var fallOuts = UnconfirmedCoinJoins.Where(x => !mempoolHashes.Contains(x)); CoinJoins.RemoveAll(x => fallOuts.Contains(x)); UnconfirmedCoinJoins.RemoveAll(x => fallOuts.Contains(x)); } uint256 coinJoinHash = round.CoinJoin.GetHash(); CoinJoins.Add(coinJoinHash); UnconfirmedCoinJoins.Add(coinJoinHash); LastSuccessfulCoinJoinTime = DateTimeOffset.UtcNow; await File.AppendAllLinesAsync(CoinJoinsFilePath, new[] { coinJoinHash.ToString() }).ConfigureAwait(false); // When a round succeeded, adjust the denomination as to users still be able to register with the latest round's active output amount. IEnumerable <(Money value, int count)> outputs = round.CoinJoin.GetIndistinguishableOutputs(includeSingle: true); var bestOutput = outputs.OrderByDescending(x => x.count).FirstOrDefault(); if (bestOutput != default) { Money activeOutputAmount = bestOutput.value; int currentConfirmationTarget = await AdjustConfirmationTargetAsync(lockCoinJoins : false).ConfigureAwait(false); var fees = await CoordinatorRound.CalculateFeesAsync(RpcClient, currentConfirmationTarget).ConfigureAwait(false); feePerInputs = fees.feePerInputs; feePerOutputs = fees.feePerOutputs; Money newDenominationToGetInWithactiveOutputs = activeOutputAmount - (feePerInputs + (2 * feePerOutputs)); if (newDenominationToGetInWithactiveOutputs < RoundConfig.Denomination) { if (newDenominationToGetInWithactiveOutputs > Money.Coins(0.01m)) { RoundConfig.Denomination = newDenominationToGetInWithactiveOutputs; RoundConfig.ToFile(); } } } }
private async void Round_StatusChangedAsync(object sender, CcjRoundStatus status) { try { var round = sender as CcjRound; Money feePerInputs = null; Money feePerOutputs = null; // If success save the coinjoin. if (status == CcjRoundStatus.Succeded) { using (await CoinJoinsLock.LockAsync()) { uint256 coinJoinHash = round.SignedCoinJoin.GetHash(); CoinJoins.Add(coinJoinHash); await File.AppendAllLinesAsync(CoinJoinsFilePath, new[] { coinJoinHash.ToString() }); // When a round succeeded, adjust the denomination as to users still be able to register with the latest round's active output amount. IEnumerable <(Money value, int count)> outputs = round.SignedCoinJoin.GetIndistinguishableOutputs(includeSingle: true); var bestOutput = outputs.OrderByDescending(x => x.count).FirstOrDefault(); if (bestOutput != default) { Money activeOutputAmount = bestOutput.value; int currentConfirmationTarget = await AdjustConfirmationTargetAsync(lockCoinJoins : false); var fees = await CcjRound.CalculateFeesAsync(RpcClient, currentConfirmationTarget); feePerInputs = fees.feePerInputs; feePerOutputs = fees.feePerOutputs; Money newDenominationToGetInWithactiveOutputs = activeOutputAmount - (feePerInputs + (2 * feePerOutputs)); if (newDenominationToGetInWithactiveOutputs < RoundConfig.Denomination) { if (newDenominationToGetInWithactiveOutputs > Money.Coins(0.01m)) { RoundConfig.Denomination = newDenominationToGetInWithactiveOutputs; await RoundConfig.ToFileAsync(); } } } } } // If aborted in signing phase, then ban Alices that did not sign. if (status == CcjRoundStatus.Aborted && round.Phase == CcjRoundPhase.Signing) { IEnumerable <Alice> alicesDidntSign = round.GetAlicesByNot(AliceState.SignedCoinJoin, syncLock: false); CcjRound nextRound = GetCurrentInputRegisterableRoundOrDefault(syncLock: false); if (nextRound != null) { int nextRoundAlicesCount = nextRound.CountAlices(syncLock: false); var alicesSignedCount = round.AnonymitySet - alicesDidntSign.Count(); // New round's anonset should be the number of alices that signed in this round. // Except if the number of alices in the next round is already larger. var newAnonymitySet = Math.Max(alicesSignedCount, nextRoundAlicesCount); // But it cannot be larger than the current anonset of that round. newAnonymitySet = Math.Min(newAnonymitySet, nextRound.AnonymitySet); // Only change the anonymity set of the next round if new anonset does not equal and newanonset is larger than 1. if (nextRound.AnonymitySet != newAnonymitySet && newAnonymitySet > 1) { nextRound.UpdateAnonymitySet(newAnonymitySet, syncLock: false); if (nextRoundAlicesCount >= nextRound.AnonymitySet) { // Progress to the next phase, which will be OutputRegistration await nextRound.ExecuteNextPhaseAsync(CcjRoundPhase.ConnectionConfirmation); } } } foreach (Alice alice in alicesDidntSign) // Because the event sometimes is raised from inside the lock. { // If it is from any coinjoin, then do not ban. IEnumerable <OutPoint> utxosToBan = alice.Inputs.Select(x => x.Outpoint); await UtxoReferee.BanUtxosAsync(1, DateTimeOffset.UtcNow, forceNoted : false, round.RoundId, utxosToBan.ToArray()); } } // If finished start a new round. if (status == CcjRoundStatus.Aborted || status == CcjRoundStatus.Succeded) { round.StatusChanged -= Round_StatusChangedAsync; round.CoinJoinBroadcasted -= Round_CoinJoinBroadcasted; await MakeSureTwoRunningRoundsAsync(feePerInputs, feePerOutputs); } } catch (Exception ex) { Logger.LogWarning(ex); } }
public RobotAction Tick(int robotId, RoundConfig config, GameState state) { RobotState selfRobot = state.robots[robotId]; RobotAction action = new RobotAction(); if (!selfRobot.isAlive) { return(action); } List <string> friendRobots = new List <string>() { "Ryzhov", "Haritonov", "Nikandrov", "Sinyavsky", "Frolov", "Orlov", "Kamshilov" }; decimal MIN_ENERGY_TO_GO_RELOAD = 0.85m; decimal MIN_HEALTH_TO_GO_RELOAD = 0.85m; decimal MAX_ATTACK_DISTANCE_RATIO = 30m; List <Point> healthPoints = state.points.Where(p => p.type == PointType.Health).ToList(); List <Point> energyPoints = state.points.Where(p => p.type == PointType.Energy).ToList(); bool hasNearestHealth = true; bool hasNearestEnergy = true; Point nearestHealth = null; decimal minDistH = 10000000m; int indexH = -1; for (int i = 0; i < healthPoints.Count; i++) { Point p = healthPoints[i]; decimal dist = GetDistance(p.X, p.Y, selfRobot.X, selfRobot.Y); if (dist < minDistH) { minDistH = dist; indexH = i; } } if (indexH >= 0) { nearestHealth = healthPoints[indexH]; } else { hasNearestHealth = false; } Point nearestEnergy = null; decimal minDistE = 10000000m; int indexE = -1; for (int i = 0; i < energyPoints.Count; i++) { Point p = energyPoints[i]; decimal dist = GetDistance(p.X, p.Y, selfRobot.X, selfRobot.Y); if (dist < minDistE) { minDistE = dist; indexE = i; } } if (indexE >= 0) { nearestEnergy = energyPoints[indexE]; } else { hasNearestEnergy = false; } decimal energyRest = selfRobot.energy / (decimal)config.max_energy; decimal healthRest = (selfRobot.speed + selfRobot.defence + selfRobot.attack) / (decimal)config.max_health; decimal step = GetMaxCurrentStep(selfRobot, config); decimal attackRadius = GetMaxCurrentAttackRadius(selfRobot, config); decimal attackPower = GetMaxCurrentAttackPower(selfRobot, config); if ((energyRest <= MIN_ENERGY_TO_GO_RELOAD && hasNearestEnergy) || (healthRest <= MIN_HEALTH_TO_GO_RELOAD && hasNearestHealth) || !done) { int dx = 0; int dy = 0; done = false; if (energyRest >= 0.99m || healthRest >= 0.99m) { done = true; } if (healthRest <= MIN_HEALTH_TO_GO_RELOAD && nearestHealth != null) { Coord deltaCoord = GetCoordXYStepToPoint(nearestHealth, selfRobot, step); if (Math.Abs(selfRobot.Y - nearestHealth.Y) <= 1) { deltaCoord.Y = (selfRobot.Y - nearestHealth.Y) * -1; } if (Math.Abs(selfRobot.X - nearestHealth.X) <= 1) { deltaCoord.X = (selfRobot.X - nearestHealth.X) * -1; } bool checkStep = CheckStepFieldBorders(selfRobot, config, deltaCoord); if (checkStep) { action.dX = deltaCoord.X; action.dY = deltaCoord.Y; action.targetId = state.robots[robotId > 0 ? 0 : 1].id; } } else if (energyRest <= MIN_ENERGY_TO_GO_RELOAD && nearestEnergy != null) { Coord deltaCoord = GetCoordXYStepToPoint(nearestEnergy, selfRobot, step); if (Math.Abs(selfRobot.Y - nearestEnergy.Y) <= 1) { deltaCoord.Y = (selfRobot.Y - nearestEnergy.Y) * -1; } if (Math.Abs(selfRobot.X - nearestEnergy.X) <= 1) { deltaCoord.X = (selfRobot.X - nearestEnergy.X) * -1; } bool checkStep = CheckStepFieldBorders(selfRobot, config, deltaCoord); if (checkStep) { action.dX = deltaCoord.X; action.dY = deltaCoord.Y; action.targetId = state.robots[robotId > 0 ? 0 : 1].id; } } } else { decimal distToNearestAlienRobot = 10000000; List <RobotState> nearRobots = new List <RobotState>(); foreach (RobotState item in state.robots) { if (selfRobot.id != item.id && !friendRobots.Contains(item.name)) { decimal dist = GetDistance(item.X, item.Y, selfRobot.X, selfRobot.Y); if (dist <= attackRadius * MAX_ATTACK_DISTANCE_RATIO) { nearRobots.Add(item); } } } nearRobots = nearRobots.Where(r => r.isAlive == true).OrderBy(r => r.defence).ToList(); bool foundAlienToAtack = false; int prevA = selfRobot.attack; int prevD = selfRobot.defence; foundAlienToAtack = CountAction(config, selfRobot, action, step, attackRadius, attackPower, nearRobots); if (!foundAlienToAtack) { RobotState ar = GetNearestAlienRobotId(state, selfRobot, friendRobots); Coord deltaCoord = GetCoordXYStepToPoint(new Point() { X = ar.X, Y = ar.Y }, selfRobot, step); bool checkStep = CheckStepFieldBorders(selfRobot, config, deltaCoord); if (checkStep) { action.dX = deltaCoord.X; action.dY = deltaCoord.Y; action.targetId = ar.id; } else { action.dX = 0; } } } battlestep++; return(action); }
public RobotAction Tick(int robotId, RoundConfig config, GameState state) { int MinDistance = 999999; coords NextCoords = new coords(); RobotState self = state.robots[robotId]; RobotAction action = new RobotAction(); action.targetId = -1; foreach (Point P in state.points) { int a = TakeDistance(self.X, self.Y, P.X, P.Y); if (P.type == PointType.Energy && (a < MinDistance)) { MinDistance = a; NextCoords.x = P.X; NextCoords.y = P.Y; } } int enemy_id = -1; coords destination = new coords(); destination = MoveTo(self, config, NextCoords); coords destination2 = new coords(); destination2 = MoveTo(self, config, NextCoords); action.dX = destination.x; action.dY = destination.y; int maxdefdistance = 10 * config.max_radius * self.speed / config.max_health * self.energy / config.max_energy; bool attacked = false; int enemy_id1 = -1; for (int id = 0; id < state.robots.Count; id++) { RobotState rstates = state.robots[id]; if (rstates.name != self.name) { int enemy_distance_attack = 10 * config.max_radius * rstates.speed / config.max_health * rstates.energy / config.max_energy; int distance = TakeDistance(self.X, self.Y, rstates.X, rstates.Y); if (distance <= enemy_distance_attack && distance <= maxdefdistance) { attacked = true; enemy_id = id; action.targetId = enemy_id; } } } if ((self.attack + self.defence + self.speed) < 0.4 * config.max_health) { action.dX = destination2.x; action.dY = destination2.y; } else if (self.energy < 0.4 * config.max_energy) { action.dX = destination.x; action.dY = destination.y; } return(action); }
private bool CountAction(RoundConfig config, RobotState selfRobot, RobotAction action, decimal step, decimal attackRadius, decimal attackPower, List <RobotState> nearRobots) { bool foundAlienToAtack = false; foreach (RobotState nrb in nearRobots) { if (nrb.defence <= attackPower) { decimal dist = GetDistance(nrb.X, nrb.Y, selfRobot.X, selfRobot.Y); decimal currentStep = 0; if (dist > attackRadius) { decimal dtoa = dist - attackRadius; if (step > dtoa) { currentStep = step - dtoa; } else { currentStep = step; } } if (currentStep > 0) { Coord deltaCoord = GetCoordXYStepToPoint(new Point() { X = nrb.X, Y = nrb.Y }, selfRobot, currentStep); bool checkStep = CheckStepFieldBorders(selfRobot, config, deltaCoord); decimal diff = step - currentStep; if (diff > 0) { decimal energyPart = selfRobot.energy / (decimal)config.max_energy; decimal healthPart = (config.max_radius * selfRobot.speed) / (decimal)config.max_health; decimal necessaryV = (config.max_health * (attackRadius - diff)) / (decimal)(energyPart * config.max_radius); } if (checkStep) { action.dX = deltaCoord.X; action.dY = deltaCoord.Y; action.targetId = nrb.id; foundAlienToAtack = true; break; } else { action.dY = 0; } } else { action.dX = 0; action.dY = 0; action.targetId = nrb.id; foundAlienToAtack = true; break; } } } return(foundAlienToAtack); }
public RobotAction Tick(int robotId, RoundConfig config, GameState state) { RobotState self = state.robots[robotId]; RobotAction action = new RobotAction(); action.targetId = -1; if (self.energy > 0 && self.isAlive) { int max_distance_attack = (int)Math.Round(10 * (float)config.max_radius * (float)self.speed / (float)config.max_health * (float)self.energy / (float)config.max_energy); int health = self.attack + self.defence + self.speed; int enemy_id = -1; if (self.energy > 0.7 * config.max_energy && health > 0.7 * config.max_health) { for (int id = 0; id < state.robots.Count; id++) { RobotState rs = state.robots[id]; if (rs.name != self.name && rs.isAlive) { int enemy_distance_attack = (int)Math.Round(10 * (float)config.max_radius * (float)rs.speed / (float)config.max_health * (float)rs.energy / (float)config.max_energy); int distance = CalcDistance(self.X, self.Y, rs.X, rs.Y); if (distance <= enemy_distance_attack && distance <= max_distance_attack) { enemy_id = id; } } } } if (enemy_id > 0) { HealthRedestribution(self, config, action, 0.4f, 0.4f, 0.2f); action.targetId = enemy_id; MoveTo(robotId, config, state, action, state.robots[enemy_id].X, state.robots[enemy_id].Y); } else { bool attack_mode = false; HealthRedestribution(self, config, action, 0.0f, 0.4f, 0.6f); if (self.energy < 0.95 * config.max_energy) { Point target = GetNearestStation(robotId, config, state, PointType.Energy); MoveTo(robotId, config, state, action, target.X, target.Y); } else { if (health < 0.8 * config.max_health) { Point target_station = GetNearestStation(robotId, config, state, PointType.Health); int X = target_station.X; int Y = target_station.Y; int target_robot_id = -1; if (health > 0.4 * config.max_health) { int target_robot_dist = config.width * config.height; for (int id = 0; id < state.robots.Count; id++) { RobotState rs = state.robots[id]; if (rs.isAlive == false && (rs.attack + rs.defence + rs.speed) > 0.4 * config.max_health) { int distance = CalcDistance(self.X, self.Y, rs.X, rs.Y); if (distance < target_robot_dist) { target_robot_id = id; target_robot_dist = distance; } } } } if (target_robot_id >= 0) { RobotState taregt_robot = state.robots[target_robot_id]; if (CalcDistance(self.X, self.Y, X, Y) > CalcDistance(self.X, self.Y, taregt_robot.X, taregt_robot.Y)) { X = taregt_robot.X; Y = taregt_robot.Y; } } MoveTo(robotId, config, state, action, X, Y); } else { int targetId = GetNearestRobot(robotId, config, state); if (targetId >= 0) { attack_mode = true; RobotState target = state.robots[targetId]; MoveTo(robotId, config, state, action, target.X, target.Y); int distance = CalcDistance(self.X + action.dX, self.Y + action.dY, target.X, target.Y); if (distance <= max_distance_attack) { action.targetId = targetId; } } } } if (!attack_mode) { int target_id = -1; for (int id = 0; id < state.robots.Count; id++) { RobotState rs = state.robots[id]; if (rs.name != self.name) { int distance = CalcDistance(self.X + action.dX, self.Y + action.dY, rs.X, rs.Y); if (distance <= max_distance_attack) { target_id = id; } } } if (target_id >= 0) { action.targetId = target_id; } } } } return(action); }
public coordinates MoveTo(RoundConfig rc, RobotState self, coordinates coords) { int max_distance = 10 * rc.max_speed * self.speed / rc.max_health * self.energy / rc.max_energy; coordinates coordsRes = new coordinates(); coordinates coordsTry = new coordinates(); int dX = coords.x - self.X; int dY = coords.y - self.Y; coordinates coordsSign = new coordinates(); coordsSign.x = sign(dX); coordsSign.y = sign(dY); coordsRes.x = 0; coordsRes.y = 0; if (Distance(self.X, self.Y, coords.x, coords.y) <= max_distance) { coordsRes.x = dX; coordsRes.y = dY; } else { coordsTry.x = 0; coordsTry.y = 0; bool ch = false; while (Pifagor(coordsTry.x, coordsTry.y) <= max_distance) { if (ch) { coordsTry.x += coordsSign.x; if (Pifagor(coordsTry.x, coordsTry.y) > max_distance) { break; } else { coordsRes.x += coordsSign.x; } } else { coordsTry.y += coordsSign.y; if (Pifagor(coordsTry.x, coordsTry.y) > max_distance) { break; } else { coordsRes.y += coordsSign.y; } } ch = !ch; } } return(coordsRes); }
public RobotAction Tick(int robotId, RoundConfig config, GameState state) { RobotState self = state.robots[robotId]; RobotAction action = new RobotAction(); action.targetId = -1; if (self.energy > 0 && self.isAlive) { // find nearest energy station int pointId = 0; int pointDist = config.height * config.width; for (int ptId = 0; ptId < state.points.Count; ptId++) { Point pt = state.points[ptId]; if (pt.type == PointType.Energy) { int ptDist = CalcDistance(self.X, self.Y, pt.X, pt.Y); if (ptDist < pointDist) { pointDist = ptDist; pointId = ptId; } } } Point targetPoint = state.points[pointId]; int maxDistance = 10 * config.max_speed * self.speed / config.max_health * self.energy / config.max_energy; if (maxDistance > 0) { if (pointDist <= maxDistance) { action.dX = targetPoint.X - self.X; action.dY = targetPoint.Y - self.Y; } else { int steps = pointDist / maxDistance + 1; action.dX = (targetPoint.X - self.X) / steps; action.dY = (targetPoint.Y - self.Y) / steps; } } // defense int targetId = -1; int targetDist = config.width * config.height; for (int rsId = 0; rsId < state.robots.Count; rsId++) { RobotState rs = state.robots[rsId]; int rsDist = CalcDistance(self.X, self.Y, rs.X, rs.Y); if (rs.name != self.name && rs.energy > 0 && rsDist < targetDist) { targetDist = rsDist; targetId = rsId; } } int maxDistanceAttack = 10 * config.max_radius * self.speed / config.max_health * self.energy / config.max_energy; if (targetDist <= maxDistanceAttack) { action.targetId = targetId; } } return(action); }
public void UpdateRoundConfig(CcjRoundConfig roundConfig) { RoundConfig.UpdateOrDefault(roundConfig); }