artificer/lib/brain.zig

105 lines
3.0 KiB
Zig

const std = @import("std");
const Api = @import("artifacts-api");
const Server = Api.Server;
const Position = Api.Position;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const CharacterTask = @import("./task.zig").Task;
const QueuedAction = @import("./action.zig").Action;
const QueuedActionResult = @import("./action.zig").ActionResult;
const Brain = @This();
name: []const u8,
action_queue: std.ArrayList(QueuedAction),
task: ?CharacterTask = null,
paused_until: ?i64 = null, // ms
pub fn init(allocator: Allocator, name: []const u8) !Brain {
return Brain{
.name = try allocator.dupe(u8, name),
.action_queue = std.ArrayList(QueuedAction).init(allocator),
};
}
pub fn deinit(self: Brain) void {
const allocator = self.action_queue.allocator;
allocator.free(self.name);
self.action_queue.deinit();
}
pub fn performNextAction(self: *Brain, api: *Server) !void {
const log = std.log.default;
assert(self.action_queue.items.len > 0);
const retry_delay = 500; // 500ms
const next_action = self.action_queue.items[0];
const action_result = try next_action.perform(api, self.name);
if (action_result.getErrorResponse()) |error_response| {
switch (error_response) {
.retry => {
self.paused_until = std.time.milliTimestamp() + retry_delay;
log.warn("[{s}] retry action", .{self.name});
return;
},
.restart => {
log.warn("[{s}] clear action queue", .{self.name});
self.action_queue.clearAndFree();
return;
},
.abort => {
log.warn("[{s}] abort action {s}", .{ self.name, @tagName(next_action) });
try action_result.getError();
// The error above should always return
unreachable;
},
.ignore => { },
}
}
_ = self.action_queue.orderedRemove(0);
if (self.task) |*task| {
task.onActionCompleted(action_result);
}
}
pub fn step(self: *Brain, api: *Api.Server) !void {
if (self.paused_until) |paused_until| {
if (std.time.milliTimestamp() < paused_until) {
return;
}
self.paused_until = null;
}
if (self.action_queue.items.len > 0) return;
if (self.task) |task| {
if (task.isComplete()) {
// if (try brain.depositItemsToBank(&self.server)) {
// continue;
// }
self.task = null;
}
}
if (self.task) |task| {
try task.queueActions(api, self.name, &self.action_queue);
}
}
pub fn cooldown(self: *Brain, api: *Server) i64 {
const character = api.store.getCharacter(self.name).?;
const cooldown_expiration: i64 = @intFromFloat(character.cooldown_expiration * std.time.ms_per_s);
if (self.paused_until) |pause_until| {
return @max(cooldown_expiration, pause_until);
} else {
return cooldown_expiration;
}
}