Skip to content
Draft
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,7 @@ ASALocalRun/

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# Replay event log files
*_events.json
replay_events.json
Binary file added .nuget/nuget.exe
Binary file not shown.
44 changes: 42 additions & 2 deletions BotRunner/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using BeholderBot;
using SC2_Connector;
using SC2_Connector.ReplaySystem;
using SC2APIProtocol;

namespace BotRunner
Expand All @@ -26,13 +27,52 @@ private static void Main(string[] args)
try
{
Controller.Connection = new GameConnection();
if (args.Length == 0)
Controller.Connection.readSettings();

// Check for replay mode
if (args.Length >= 2 && args[0] == "--replay")
{
Controller.Connection.readSettings();
// Replay mode: analyze a replay and log events
// Usage: --replay <replay_path> [observed_player_id] [output_log_path]
var replayPath = args[1];
var observedPlayerId = args.Length >= 3 ? int.Parse(args[2]) : 1;
var outputLogPath = args.Length >= 4 ? args[3] : "replay_events.json";

Logger.Info("Running in REPLAY mode");
Logger.Info($"Replay: {replayPath}");
Logger.Info($"Observed Player: {observedPlayerId}");
Logger.Info($"Output Log: {outputLogPath}");

Controller.Connection.RunReplayAndLogEvents(replayPath, observedPlayerId, outputLogPath).Wait();
}
else if (args.Length >= 2 && args[0] == "--playback")
{
// Playback mode: run bot with event playback from a log file
// Usage: --playback <event_log_path>
var eventLogPath = args[1];

Logger.Info("Running in PLAYBACK mode");
Logger.Info($"Event Log: {eventLogPath}");

// Load the event player
Controller.EventPlayer = EventPlayer.LoadFromFile(eventLogPath);
Controller.EventPlayer.Enable();

Logger.Info($"Loaded {Controller.EventPlayer.TotalEvents} events for playback");

// Run the game normally with event playback enabled
Controller.Connection.RunSinglePlayer(bot, mapName, bot.GetRace(), opponentRace, opponentDifficulty).Wait();
}
else if (args.Length == 0)
{
// Normal single player mode
Controller.Connection.RunSinglePlayer(bot, mapName, bot.GetRace(), opponentRace, opponentDifficulty).Wait();
}
else
{
// Ladder mode
Controller.Connection.RunLadder(bot, bot.GetRace(), args).Wait();
}
}
catch (Exception ex)
{
Expand Down
203 changes: 203 additions & 0 deletions IMPLEMENTATION_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# Implementation Summary

## Replay Event Logging and Playback System

This document provides a technical overview of the replay event logging and playback system implemented for the SC2 C# bot.

## Architecture

### Component Overview

```
┌─────────────────────────────────────────────────────────┐
│ BotRunner (Program.cs) │
│ Command-line argument parsing and mode selection │
└─────────────────────────────────────────────────────────┘
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌──────────┐ ┌──────────┐
│ Normal │ │ Replay │ │ Playback │
│ Mode │ │ Mode │ │ Mode │
└────────┘ └──────────┘ └──────────┘
│ │
│ │
┌─────────────────┴─────────────────┘
┌──────────────────────────────────────────────────────────┐
│ GameConnection + Controller │
│ Core game loop and SC2 API communication │
└──────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ EventLogger │ │ EventPlayer │
│ - ProcessFrame │ │ - ProcessFrame │
│ - SaveToFile │ │ - ExecuteEvent │
└──────────────────┘ └──────────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────────────┐
│ ReplayEvent │
│ JSON-serializable event data structure │
└──────────────────────────────────────────────────────────┘
```

## Data Flow

### Replay Analysis Mode

1. User runs: `BotRunner.exe --replay replay.SC2Replay 1 events.json`
2. Program.cs parses arguments and calls `GameConnection.RunReplayAndLogEvents()`
3. GameConnection starts SC2 and loads the replay
4. For each frame:
- Controller.OpenFrame() is called
- EventLogger.ProcessFrame() detects new units/buildings
- Events are logged with frame number, type, position, etc.
5. When replay ends, EventLogger.SaveToFile() writes events to JSON
6. User gets a timestamped event log file

### Playback Mode

1. User runs: `BotRunner.exe --playback events.json`
2. Program.cs loads events using `EventPlayer.LoadFromFile()`
3. EventPlayer is enabled and set on Controller
4. Normal game starts
5. For each frame:
- Controller.OpenFrame() is called
- EventPlayer.ProcessFrame() checks for events at current frame
- If events should execute, EventPlayer attempts to execute them
- Bot continues with normal AI logic
6. Events are executed in chronological order

## Key Classes

### ReplayEvent
- **Purpose**: Immutable data object representing a game event
- **Serialization**: DataContract attributes for JSON serialization
- **Properties**: Frame, EventType, UnitType, Position (X,Y,Z), PlayerId, Notes

### EventLogger
- **Purpose**: Detects and logs events during replay playback
- **Key Methods**:
- `ProcessFrame()`: Analyzes units each frame to detect new events
- `LogUnitCreated()`: Records unit/building creation
- `LogBuildingCompleted()`: Records building completion
- `SaveToFile()`: Serializes events to JSON
- `LoadFromFile()`: Deserializes events from JSON
- **State Tracking**: Maintains dictionaries to track previously seen units

### EventPlayer
- **Purpose**: Executes logged events during bot gameplay
- **Key Methods**:
- `ProcessFrame()`: Checks for events to execute at current frame
- `ExecuteEvent()`: Dispatches to specific execution handlers
- `ExecuteBuildingStarted()`: Commands worker to build
- `ExecuteUnitCreated()`: Commands structure to train unit
- **Error Handling**: Gracefully handles missing resources/tech

## Event Types

### BuildingStarted
- Triggered when a building construction begins
- Stores the exact position for reconstruction
- During playback: Finds nearest worker and issues build command

### UnitCreated
- Triggered when a unit is created/trained
- Position not critical for units (they're created at structures)
- During playback: Finds appropriate production structure and issues train command

### BuildingCompleted
- Triggered when a building finishes construction
- Informational only (buildings complete automatically)
- During playback: Logged but no action taken

## Integration Points

### Controller.OpenFrame()
Called every game frame. If EventPlayer is enabled, calls `EventPlayer.ProcessFrame()` to execute any pending events.

### GameConnection.RunReplayWithLogging()
Custom game loop for replay mode. Similar to normal game loop but uses EventLogger instead of bot AI.

### Program.Main()
Argument parsing:
- `--replay <path> [player] [output]`: Replay analysis mode
- `--playback <path>`: Playback mode
- No args: Normal single-player mode
- Args without flags: Ladder mode

## File Format

Event logs are JSON arrays of ReplayEvent objects:

```json
[
{
"Frame": 224,
"EventType": "BuildingStarted",
"UnitType": 86,
"PositionX": 125.5,
"PositionY": 132.0,
"PositionZ": 11.98,
"PlayerId": 1,
"Notes": ""
}
]
```

## Technical Decisions

### JSON Serialization
- Used `DataContractJsonSerializer` for .NET Framework 4.7.2 compatibility
- Could migrate to System.Text.Json if upgrading to .NET Core/5+

### Building Detection
- Uses `BuildingType.GetBuildingSize()` to identify buildings
- Try/catch pattern: if size retrieval succeeds, it's a building

### Event Timing
- Frame-based timing ensures deterministic playback
- Events execute at exact same game time as in replay

### Error Tolerance
- Playback mode logs failures but continues
- Allows partial execution when resources/tech unavailable

## Limitations and Future Enhancements

### Current Limitations
1. Only tracks building and unit creation (not upgrades, abilities, etc.)
2. Playback doesn't verify resources before attempting actions
3. No support for complex timing adjustments (e.g., delayed builds)

### Potential Enhancements
1. Add upgrade tracking
2. Add ability usage tracking (e.g., Chrono Boost, Inject Larvae)
3. Implement resource-aware playback scheduling
4. Add support for multi-player replays
5. Create UI for event log visualization/editing
6. Add event filtering/grouping capabilities

## Testing Recommendations

1. **Replay Analysis**: Test with various replay files from different players
2. **Event Logging**: Verify all building types are detected correctly
3. **Playback**: Test that events execute in correct order
4. **Edge Cases**: Test with replays that have unusual build orders
5. **Resource Constraints**: Test playback when bot has fewer resources than replay
6. **Integration**: Ensure compatibility with existing bot AI

## Performance Considerations

- Event processing is O(n) where n = number of units/events
- JSON serialization is relatively fast for typical event counts (<1000 events)
- Memory usage is minimal (events are small objects)
- No significant impact on game performance

## Conclusion

This system provides a solid foundation for replay analysis and build order replication. The modular design allows for easy extension and customization while maintaining compatibility with the existing bot framework.
Loading