sami test
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Orientation="Horizontal" Spacing="8">
|
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Orientation="Horizontal" Spacing="8">
|
||||||
<Button x:Name="StartButton" Content="Start Bot" Width="120"/>
|
<Button x:Name="StartButton" Content="Start Bot" Width="120"/>
|
||||||
<Button x:Name="StopButton" Content="Stop Bot" Width="120" IsEnabled="False"/>
|
<Button x:Name="StopButton" Content="Stop Bot" Width="120" IsEnabled="False"/>
|
||||||
|
<CheckBox x:Name="MultiplayerCheckBox" Content="Multiplayer" VerticalAlignment="Center"/>
|
||||||
<TextBlock Text="API Key:" VerticalAlignment="Center"/>
|
<TextBlock Text="API Key:" VerticalAlignment="Center"/>
|
||||||
<TextBox x:Name="ApiKeyBox" Width="360" Watermark="GUID player token"/>
|
<TextBox x:Name="ApiKeyBox" Width="360" Watermark="GUID player token"/>
|
||||||
<TextBlock x:Name="StatusText" VerticalAlignment="Center" Text="Idle"/>
|
<TextBlock x:Name="StatusText" VerticalAlignment="Center" Text="Idle"/>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public partial class MainWindow : Window
|
|||||||
};
|
};
|
||||||
|
|
||||||
private readonly string _configuredApiKey = Program.Configuration["APIKEY"] ?? string.Empty;
|
private readonly string _configuredApiKey = Program.Configuration["APIKEY"] ?? string.Empty;
|
||||||
|
private readonly bool _multiplayerModeDefault = bool.TryParse(Program.Configuration["MULTIPLAYER"], out var multiplayer) && multiplayer;
|
||||||
private readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(8) };
|
private readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(8) };
|
||||||
private readonly DigitalDojoApiClient _client;
|
private readonly DigitalDojoApiClient _client;
|
||||||
private readonly ObservableCollection<string> _logEntries = [];
|
private readonly ObservableCollection<string> _logEntries = [];
|
||||||
@@ -85,6 +86,7 @@ public partial class MainWindow : Window
|
|||||||
BuildKnowledgeGrid();
|
BuildKnowledgeGrid();
|
||||||
|
|
||||||
ApiKeyBox.Text = _configuredApiKey;
|
ApiKeyBox.Text = _configuredApiKey;
|
||||||
|
MultiplayerCheckBox.IsChecked = _multiplayerModeDefault;
|
||||||
LogList.ItemsSource = _logEntries;
|
LogList.ItemsSource = _logEntries;
|
||||||
|
|
||||||
StartButton.Click += async (_, _) => await StartBotAsync();
|
StartButton.Click += async (_, _) => await StartBotAsync();
|
||||||
@@ -122,6 +124,7 @@ public partial class MainWindow : Window
|
|||||||
StartButton.IsEnabled = false;
|
StartButton.IsEnabled = false;
|
||||||
StopButton.IsEnabled = true;
|
StopButton.IsEnabled = true;
|
||||||
ApiKeyBox.IsEnabled = false;
|
ApiKeyBox.IsEnabled = false;
|
||||||
|
MultiplayerCheckBox.IsEnabled = false;
|
||||||
|
|
||||||
ResetKnowledgeState();
|
ResetKnowledgeState();
|
||||||
|
|
||||||
@@ -185,6 +188,7 @@ public partial class MainWindow : Window
|
|||||||
StartButton.IsEnabled = true;
|
StartButton.IsEnabled = true;
|
||||||
StopButton.IsEnabled = false;
|
StopButton.IsEnabled = false;
|
||||||
ApiKeyBox.IsEnabled = true;
|
ApiKeyBox.IsEnabled = true;
|
||||||
|
MultiplayerCheckBox.IsEnabled = true;
|
||||||
SetStatus("Stopped.");
|
SetStatus("Stopped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,6 +215,13 @@ public partial class MainWindow : Window
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsMultiplayerMode)
|
||||||
|
{
|
||||||
|
// In multiplayer, the lobby controls game creation/start.
|
||||||
|
AppendLog("Multiplayer mode enabled; waiting for lobby game start (no create call).");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var created = await _client.CreateAsync(_playerToken, ct);
|
var created = await _client.CreateAsync(_playerToken, ct);
|
||||||
@@ -501,6 +512,12 @@ public partial class MainWindow : Window
|
|||||||
// Teleport closer to enemy for aggressive positioning
|
// Teleport closer to enemy for aggressive positioning
|
||||||
var moveTowardX = targetX > 0 ? targetX - 1 : targetX + 1;
|
var moveTowardX = targetX > 0 ? targetX - 1 : targetX + 1;
|
||||||
var moveTowardY = targetY > 0 ? targetY - 1 : targetY + 1;
|
var moveTowardY = targetY > 0 ? targetY - 1 : targetY + 1;
|
||||||
|
var teleportDirection = DirectionFromVector(moveTowardX, moveTowardY);
|
||||||
|
if (IsDirectionUnsafeForHighSpeedMove(teleportDirection))
|
||||||
|
{
|
||||||
|
moveTowardX = targetX;
|
||||||
|
moveTowardY = targetY;
|
||||||
|
}
|
||||||
|
|
||||||
return new BotDecision(
|
return new BotDecision(
|
||||||
"teleport-aggro",
|
"teleport-aggro",
|
||||||
@@ -509,16 +526,26 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
var response = await _client.TeleportAsync(_playerToken, moveTowardX, moveTowardY, ct);
|
var response = await _client.TeleportAsync(_playerToken, moveTowardX, moveTowardY, ct);
|
||||||
MarkUsed(BotAction.Teleport);
|
MarkUsed(BotAction.Teleport);
|
||||||
if (response.Executed)
|
if (response.Executed && !response.LandedInWall)
|
||||||
{
|
{
|
||||||
_x = moveTowardX;
|
_x = moveTowardX;
|
||||||
_y = moveTowardY;
|
_y = moveTowardY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.LandedInWall)
|
||||||
|
{
|
||||||
|
var dir = DirectionFromVector(moveTowardX, moveTowardY);
|
||||||
|
_blockedDirectionTicks.TryGetValue(dir, out var blocked);
|
||||||
|
_blockedDirectionTicks[dir] = Math.Max(blocked, 14);
|
||||||
|
_survivalTicks = Math.Max(_survivalTicks, 10);
|
||||||
|
_sessionLogger?.LogEvent("teleport-wall", $"x={moveTowardX};y={moveTowardY}");
|
||||||
|
}
|
||||||
|
|
||||||
return response.Executed;
|
return response.Executed;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ready(BotAction.Dash) && TryGetAggressiveDashDirection(predictedEnemy, bestSight, out var dashDirection, out var dashReason))
|
if (Ready(BotAction.Dash) && TryGetAggressiveDashDirection(predictedEnemy, bestSight.Key, bestSight.Value, out var dashDirection, out var dashReason))
|
||||||
{
|
{
|
||||||
return new BotDecision(
|
return new BotDecision(
|
||||||
"dash-aggro",
|
"dash-aggro",
|
||||||
@@ -529,7 +556,19 @@ public partial class MainWindow : Window
|
|||||||
MarkUsed(BotAction.Dash);
|
MarkUsed(BotAction.Dash);
|
||||||
if (response.Executed)
|
if (response.Executed)
|
||||||
{
|
{
|
||||||
ApplyMovement(dashDirection, Math.Max(response.BlocksDashed, 1));
|
var movedBlocks = Math.Max(response.BlocksDashed, 0);
|
||||||
|
if (movedBlocks > 0)
|
||||||
|
{
|
||||||
|
ApplyMovement(dashDirection, movedBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.DamageTaken > 0)
|
||||||
|
{
|
||||||
|
_blockedDirectionTicks.TryGetValue(dashDirection, out var blocked);
|
||||||
|
_blockedDirectionTicks[dashDirection] = Math.Max(blocked, 12);
|
||||||
|
_survivalTicks = Math.Max(_survivalTicks, 8);
|
||||||
|
_sessionLogger?.LogEvent("dash-self-damage", $"dir={dashDirection};damage={response.DamageTaken};blocks={response.BlocksDashed}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.Executed;
|
return response.Executed;
|
||||||
@@ -581,7 +620,20 @@ public partial class MainWindow : Window
|
|||||||
MarkUsed(BotAction.Dash);
|
MarkUsed(BotAction.Dash);
|
||||||
if (response.Executed)
|
if (response.Executed)
|
||||||
{
|
{
|
||||||
ApplyMovement(retreatDirection, Math.Max(response.BlocksDashed, 1));
|
var movedBlocks = Math.Max(response.BlocksDashed, 0);
|
||||||
|
if (movedBlocks > 0)
|
||||||
|
{
|
||||||
|
ApplyMovement(retreatDirection, movedBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.DamageTaken > 0)
|
||||||
|
{
|
||||||
|
_blockedDirectionTicks.TryGetValue(retreatDirection, out var blocked);
|
||||||
|
_blockedDirectionTicks[retreatDirection] = Math.Max(blocked, 12);
|
||||||
|
_survivalTicks = Math.Max(_survivalTicks, 10);
|
||||||
|
_sessionLogger?.LogEvent("dash-self-damage", $"dir={retreatDirection};damage={response.DamageTaken};blocks={response.BlocksDashed}");
|
||||||
|
}
|
||||||
|
|
||||||
_escapeDirection = retreatDirection;
|
_escapeDirection = retreatDirection;
|
||||||
_escapeLockTicks = Math.Max(_escapeLockTicks, EscapeLockTicks(profile));
|
_escapeLockTicks = Math.Max(_escapeLockTicks, EscapeLockTicks(profile));
|
||||||
}
|
}
|
||||||
@@ -1025,7 +1077,8 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
private bool TryGetAggressiveDashDirection(
|
private bool TryGetAggressiveDashDirection(
|
||||||
(int X, int Y)? predictedEnemy,
|
(int X, int Y)? predictedEnemy,
|
||||||
KeyValuePair<Direction, PeekEntitiesAsyncResponse>? bestSight,
|
Direction? sightDirection,
|
||||||
|
PeekEntitiesAsyncResponse? sightResponse,
|
||||||
out Direction direction,
|
out Direction direction,
|
||||||
out string reason)
|
out string reason)
|
||||||
{
|
{
|
||||||
@@ -1033,20 +1086,24 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
var target = predictedEnemy ?? _nearestEnemy.Value;
|
var target = predictedEnemy ?? _nearestEnemy.Value;
|
||||||
var dist = Math.Abs(target.X) + Math.Abs(target.Y);
|
var dist = Math.Abs(target.X) + Math.Abs(target.Y);
|
||||||
if (dist >= 2 && dist <= 6)
|
if (dist >= 2 && dist <= 4)
|
||||||
{
|
{
|
||||||
direction = DirectionFromVector(target.X, target.Y);
|
var candidate = DirectionFromVector(target.X, target.Y);
|
||||||
|
if (!IsDirectionUnsafeForHighSpeedMove(candidate))
|
||||||
|
{
|
||||||
|
direction = candidate;
|
||||||
reason = $"Aggressive gap-close toward enemy at {direction} (predicted distance {dist}).";
|
reason = $"Aggressive gap-close toward enemy at {direction} (predicted distance {dist}).";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bestSight.HasValue && bestSight.Value.Value.Executed && bestSight.Value.Value.PlayersInSight > 0)
|
if (sightDirection.HasValue && sightResponse is not null && sightResponse.Executed && sightResponse.PlayersInSight > 0)
|
||||||
{
|
{
|
||||||
var dist = bestSight.Value.Value.SightedPlayerDistance ?? 99;
|
var dist = sightResponse.SightedPlayerDistance ?? 99;
|
||||||
if (dist >= 2 && dist <= 5)
|
if (dist >= 2 && dist <= 4 && !IsDirectionUnsafeForHighSpeedMove(sightDirection.Value))
|
||||||
{
|
{
|
||||||
direction = bestSight.Value.Key;
|
direction = sightDirection.Value;
|
||||||
reason = $"Enemy visible at {direction} ({dist} dist); dash to force close-range combat.";
|
reason = $"Enemy visible at {direction} ({dist} dist); dash to force close-range combat.";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1057,6 +1114,16 @@ public partial class MainWindow : Window
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsDirectionUnsafeForHighSpeedMove(Direction direction)
|
||||||
|
{
|
||||||
|
if (_blockedDirectionTicks.TryGetValue(direction, out var blocked) && blocked > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DeathHeatFor(direction) >= 4.0;
|
||||||
|
}
|
||||||
|
|
||||||
private void MarkVisit(int x, int y, double amount)
|
private void MarkVisit(int x, int y, double amount)
|
||||||
{
|
{
|
||||||
var key = (x, y);
|
var key = (x, y);
|
||||||
@@ -1209,6 +1276,8 @@ public partial class MainWindow : Window
|
|||||||
Dispatcher.UIThread.Post(() => StatusText.Text = text);
|
Dispatcher.UIThread.Post(() => StatusText.Text = text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsMultiplayerMode => MultiplayerCheckBox.IsChecked == true;
|
||||||
|
|
||||||
private void AppendLog(string message)
|
private void AppendLog(string message)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
|||||||
Reference in New Issue
Block a user