const std = @import("std"); const rl = @import("raylib"); const spawn_area = @import("spawn-area.zig"); const structures = @import("structures.zig"); pub const Areas = struct { allocator: std.mem.Allocator, areas: []spawn_area.SpawnArea, pub fn init(allocator: std.mem.Allocator, size: usize) !Areas { const values = std.enums.values(structures.AreaLocation); var max_areas = size; if (size > values.len) max_areas = values.len; var used_areas = std.ArrayList(structures.AreaLocation).init(allocator); defer used_areas.deinit(); var prng = std.Random.DefaultPrng.init(blk: { var seed: u64 = undefined; try std.posix.getrandom(std.mem.asBytes(&seed)); break :blk seed; }); const rand = prng.random(); const area_data = try allocator.alloc(spawn_area.SpawnArea, size); for (area_data) |*area| { // give us all valid values we can use for AreaLocation const valid_values = try getEnumValuesMinusUsed(allocator, used_areas, values); defer allocator.free(valid_values); const num = rand.intRangeAtMost(usize, 0, valid_values.len - 1); // random number // here we create new spawnarea area.* = spawn_area.SpawnArea.init(valid_values[num]); try used_areas.append(valid_values[num]); } return Areas{ .allocator = allocator, .areas = area_data, }; } pub fn deinit(self: *Areas) void { self.allocator.free(self.areas); } pub fn draw(self: *const Areas) void { for (self.areas) |area| { area.draw(); } } fn getEnumValuesMinusUsed(allocator: std.mem.Allocator, used_values: std.ArrayList(structures.AreaLocation), values: []const structures.AreaLocation) ![]structures.AreaLocation { var valuesToRandomise = try allocator.alloc(structures.AreaLocation, values.len - used_values.items.len); var i: usize = 0; outer: for (values) |value| { for (used_values.items) |used_val| { if (value == used_val) { continue :outer; } } // this value is clean and can get put into values good for randomisation valuesToRandomise[i] = value; i += 1; } return valuesToRandomise; } };