add creation of sub goals through requirements
This commit is contained in:
parent
df56eceab6
commit
87c09f1e27
@ -23,6 +23,7 @@ pub const Equipment = @import("./schemas/equipment.zig");
|
||||
pub const Craft = @import("./schemas/craft.zig");
|
||||
pub const Resource = @import("./schemas/resource.zig");
|
||||
pub const MoveResult = @import("./schemas/move_result.zig");
|
||||
pub const SimpleItem = @import("./schemas/simple_item.zig");
|
||||
const SkillUsageResult = @import("./schemas/skill_usage_result.zig");
|
||||
pub const GatherResult = SkillUsageResult;
|
||||
pub const CraftResult = SkillUsageResult;
|
||||
|
@ -30,10 +30,10 @@ pub fn BoundedArray(comptime slot_count: u32) type {
|
||||
const Items = std.BoundedArray(SimpleItem, slot_count);
|
||||
|
||||
return struct {
|
||||
items: Items,
|
||||
items: Items = .{ .len = 0 },
|
||||
|
||||
pub fn init() @This() {
|
||||
return @This(){ .items = Items.init(0) catch unreachable };
|
||||
return @This(){};
|
||||
}
|
||||
|
||||
pub fn parse(store: *Store, slots_array: std.json.Array) !@This() {
|
||||
@ -89,6 +89,16 @@ pub fn BoundedArray(comptime slot_count: u32) type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addAssumeCapacity(self: *@This(), id: Store.Id, quantity: u64) void {
|
||||
if (quantity == 0) return;
|
||||
|
||||
if (self.findSlot(id)) |slot| {
|
||||
slot.quantity += quantity;
|
||||
} else {
|
||||
self.items.appendAssumeCapacity(SimpleItem.init(id, quantity));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addSlice(self: *@This(), items: []const SimpleItem) void {
|
||||
for (items) |item| {
|
||||
self.add(item.id, item.quantity);
|
||||
@ -117,7 +127,7 @@ pub fn BoundedArray(comptime slot_count: u32) type {
|
||||
return count;
|
||||
}
|
||||
|
||||
pub fn slice(self: *@This()) []SimpleItem {
|
||||
pub fn slice(self: @This()) []const SimpleItem {
|
||||
return self.items.slice();
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ pub fn main() !void {
|
||||
_ = try artificer.appendGoal(Artificer.Goal{
|
||||
.craft = .{
|
||||
.item = store.items.getId("copper").?,
|
||||
.quantity = 3
|
||||
.quantity = 2
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,12 +1,20 @@
|
||||
// zig fmt: off
|
||||
const Api = @import("artifacts-api");
|
||||
const Artificer = @import("./root.zig");
|
||||
const Requirements = Artificer.Requirements;
|
||||
|
||||
const Goal = @This();
|
||||
|
||||
item: Api.Store.Id,
|
||||
quantity: u64,
|
||||
|
||||
fn getCraftMultiples(self: Goal, craft: Api.Craft) u64 {
|
||||
return @intFromFloat(@ceil(
|
||||
@as(f32, @floatFromInt(self.quantity)) /
|
||||
@as(f32, @floatFromInt(craft.quantity))
|
||||
));
|
||||
}
|
||||
|
||||
pub fn tick(self: *Goal, goal_id: Artificer.GoalId, artificer: *Artificer) !void {
|
||||
const store = artificer.server.store;
|
||||
const character = store.characters.get(artificer.character).?;
|
||||
@ -24,18 +32,6 @@ pub fn tick(self: *Goal, goal_id: Artificer.GoalId, artificer: *Artificer) !void
|
||||
return error.SkillTooLow;
|
||||
}
|
||||
|
||||
const craft_multiples: u64 = @intFromFloat(@ceil(
|
||||
@as(f32, @floatFromInt(self.quantity)) /
|
||||
@as(f32, @floatFromInt(craft.quantity))
|
||||
));
|
||||
|
||||
for (craft.items.items.slice()) |craft_item| {
|
||||
const inventory_item_quantity = character.inventory.getQuantity(craft_item.id);
|
||||
if (inventory_item_quantity < craft_item.quantity * craft_multiples) {
|
||||
return error.NotEnoughItems;
|
||||
}
|
||||
}
|
||||
|
||||
const workshop_position = artificer.findNearestWorkstation(craft.skill).?;
|
||||
if (!workshop_position.eql(character.position)) {
|
||||
artificer.queued_actions.appendAssumeCapacity(.{
|
||||
@ -51,6 +47,21 @@ pub fn tick(self: *Goal, goal_id: Artificer.GoalId, artificer: *Artificer) !void
|
||||
});
|
||||
}
|
||||
|
||||
pub fn requirements(self: Goal, artificer: *Artificer) Artificer.Requirements {
|
||||
var reqs: Artificer.Requirements = .{};
|
||||
|
||||
const store = artificer.server.store;
|
||||
const item = store.items.get(self.item).?;
|
||||
const craft = item.craft.?;
|
||||
const craft_multiples = self.getCraftMultiples(craft);
|
||||
|
||||
for (craft.items.slice()) |craft_item| {
|
||||
reqs.items.addAssumeCapacity(craft_item.id, craft_item.quantity * craft_multiples);
|
||||
}
|
||||
|
||||
return reqs;
|
||||
}
|
||||
|
||||
pub fn onActionCompleted(self: *Goal, goal_id: Artificer.GoalId, result: Artificer.ActionResult) void {
|
||||
_ = goal_id;
|
||||
|
||||
|
@ -34,6 +34,15 @@ pub fn tick(self: *Goal, goal_id: Artificer.GoalId, artificer: *Artificer) void
|
||||
});
|
||||
}
|
||||
|
||||
pub fn requirements(self: Goal, artificer: *Artificer) Artificer.Requirements {
|
||||
_ = self;
|
||||
_ = artificer;
|
||||
|
||||
const reqs: Artificer.Requirements = .{};
|
||||
// TODO: add skill requirement
|
||||
return reqs;
|
||||
}
|
||||
|
||||
pub fn onActionCompleted(self: *Goal, goal_id: Artificer.GoalId, result: Artificer.ActionResult) void {
|
||||
_ = goal_id;
|
||||
|
||||
|
64
lib/root.zig
64
lib/root.zig
@ -16,7 +16,11 @@ pub const GoalId = packed struct {
|
||||
const Index = u11;
|
||||
|
||||
generation: Generation,
|
||||
index: Index
|
||||
index: Index,
|
||||
|
||||
pub fn eql(self: GoalId, other: GoalId) bool {
|
||||
return self.index == other.index and self.generation == other.generation;
|
||||
}
|
||||
};
|
||||
|
||||
const max_goals = std.math.maxInt(GoalId.Index);
|
||||
@ -35,6 +39,13 @@ pub const Goal = union(enum) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn requirements(self: Goal, artificer: *Artificer) Requirements {
|
||||
return switch (self) {
|
||||
.gather => |gather| gather.requirements(artificer),
|
||||
.craft => |craft| craft.requirements(artificer),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn onActionCompleted(self: *Goal, goal_id: Artificer.GoalId, result: Artificer.ActionResult) void {
|
||||
switch (self.*) {
|
||||
.gather => |*gather| gather.onActionCompleted(goal_id, result),
|
||||
@ -45,6 +56,7 @@ pub const Goal = union(enum) {
|
||||
|
||||
const GoalSlot = struct {
|
||||
generation: GoalId.Generation = 0,
|
||||
parent_goal: ?GoalId = null,
|
||||
goal: ?Goal = null,
|
||||
};
|
||||
|
||||
@ -68,6 +80,16 @@ const ActionSlot = struct {
|
||||
action: Action,
|
||||
};
|
||||
|
||||
pub const Requirements = struct {
|
||||
pub const Items = Api.SimpleItem.BoundedArray(blk: {
|
||||
var max: usize = 0;
|
||||
max = @max(max, Api.Craft.max_items);
|
||||
break :blk max;
|
||||
});
|
||||
|
||||
items: Items = .{}
|
||||
};
|
||||
|
||||
const QueuedActions = std.ArrayListUnmanaged(ActionSlot);
|
||||
|
||||
server: *Api.Server,
|
||||
@ -256,8 +278,19 @@ fn getGoalCount(self: *Artificer) u32 {
|
||||
return count;
|
||||
}
|
||||
|
||||
fn hasSubGoals(self: *Artificer, goal_id: GoalId) bool {
|
||||
for (self.goal_slots) |goal_slot| {
|
||||
if (goal_slot.goal != null and goal_slot.parent_goal != null and goal_slot.parent_goal.?.eql(goal_id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn tick(self: *Artificer) !void {
|
||||
const store = self.server.store;
|
||||
const character = store.characters.get(self.character).?;
|
||||
|
||||
if (self.queued_actions.items.len > 0) {
|
||||
const expires_in = self.timeUntilCooldownExpires();
|
||||
@ -265,7 +298,6 @@ pub fn tick(self: *Artificer) !void {
|
||||
return;
|
||||
}
|
||||
|
||||
const character = store.characters.get(self.character).?;
|
||||
const action_slot = self.queued_actions.orderedRemove(0);
|
||||
const action_result = switch (action_slot.action) {
|
||||
.move => |position| ActionResult{
|
||||
@ -297,6 +329,34 @@ pub fn tick(self: *Artificer) !void {
|
||||
.generation = goal_slot.generation
|
||||
};
|
||||
|
||||
if (self.hasSubGoals(goal_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const reqs = goal.requirements(self);
|
||||
for (reqs.items.slice()) |req_item| {
|
||||
const inventory_quantity = character.inventory.getQuantity(req_item.id);
|
||||
if (inventory_quantity < req_item.quantity) {
|
||||
if (self.findBestResourceWithItem(req_item.id) != null) {
|
||||
const subgoal_id = try self.appendGoal(.{
|
||||
.gather = .{
|
||||
.item = req_item.id,
|
||||
.quantity = req_item.quantity - inventory_quantity,
|
||||
}
|
||||
});
|
||||
|
||||
const subgoal = self.getGoal(subgoal_id).?;
|
||||
subgoal.parent_goal = goal_id;
|
||||
} else {
|
||||
@panic("Not all requirements were handled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.hasSubGoals(goal_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try goal.tick(goal_id, self);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user