const std = @import("std"); const Allocator = std.mem.Allocator; const json = std.json; const prettym = @import("pretty"); const m = @import("../models.zig"); pub const Symbol = union(Symbol.Type) { sector: u8, system: Symbol.System, waypoint: Symbol.Waypoint, pub const Type = enum { sector, system, waypoint }; pub const System = struct { sector: u8, symbol: []const u8, pub fn format(this: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void { try writer.print("X{}-{s}", .{ this.sector, this.symbol }); } }; pub const Waypoint = struct { system: Symbol.System, symbol: []const u8, pub fn format(this: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void { try writer.print("{f}-{s}", .{ this.system, this.symbol }); } }; pub fn parseSlice(slice: []const u8) !Symbol { var tokens = std.mem.tokenizeScalar(u8, slice, '-'); const sector_raw = tokens.next() orelse return error.InvalidSymbol; std.debug.assert(sector_raw.len == 2); std.debug.assert(sector_raw[0] == 'X'); const sector = std.fmt.parseInt(u8, sector_raw[1..], 10) catch return error.InvalidSector; const system_raw = tokens.next(); if (system_raw) |system| { const sys = Symbol.System{ .sector = sector, .symbol = system }; if (tokens.next()) |waypoint| { return Symbol{ .waypoint = .{ .system = sys, .symbol = waypoint, } }; } return Symbol{ .system = sys }; } else { return Symbol{ .sector = sector }; } } pub fn jsonParse( allocator: Allocator, source: anytype, options: json.ParseOptions, ) json.ParseError(@TypeOf(source.*))!Symbol { const string = try json.innerParse([]const u8, allocator, source, options); return parseSlice(string) catch return error.MissingField; } pub fn format(this: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void { switch (this) { .sector => |sector| { try writer.print("X{}", .{sector}); }, inline else => |e| try writer.print("{f}", .{e}), } } pub fn pretty( this: *const @This(), comptime ctx: prettym.Context, run: *const prettym.Runtime, ) error{WriteFailed}!void { run.setColor(ctx, .value); try run.print("{f}", .{this}); run.resetColor(); } }; pub const System = struct { constellation: []const u8, symbol: Symbol, sectorSymbol: Symbol, type: Type, x: i64, y: i64, waypoints: []WaypointPreview, factions: []Faction, name: []const u8, pub const Type = enum { NEUTRON_STAR, RED_STAR, ORANGE_STAR, BLUE_STAR, YOUNG_STAR, WHITE_DWARF, BLACK_HOLE, HYPERGIANT, NEBULA, UNSTABLE, }; }; pub const Waypoint = struct { symbol: Symbol, systemSymbol: Symbol, type: Type, x: i64, y: i64, faction: Faction, traits: []m.SymbolWrapper(Trait), modifiers: []Modifier, chart: Chart, isUnderConstruction: bool, orbitals: []m.SymbolWrapper([]const u8), orbits: ?[]const u8 = null, pub fn unwrapTraits(this: *const @This(), alloc: std.mem.Allocator) ![]Trait { var buf = try alloc.alloc(Trait, this.traits.len); for (this.traits, 0..) |trait, i| { buf[i] = trait.symbol; } return buf; } pub const Type = enum { PLANET, GAS_GIANT, MOON, ORBITAL_STATION, JUMP_GATE, ASTEROID_FIELD, ASTEROID, ENGINEERED_ASTEROID, ASTEROID_BASE, NEBULA, DEBRIS_FIELD, GRAVITY_WELL, ARTIFICIAL_GRAVITY_WELL, FUEL_STATION, }; pub const Trait = enum { UNCHARTED, UNDER_CONSTRUCTION, MARKETPLACE, SHIPYARD, OUTPOST, SCATTERED_SETTLEMENTS, SPRAWLING_CITIES, MEGA_STRUCTURES, PIRATE_BASE, OVERCROWDED, HIGH_TECH, CORRUPT, BUREAUCRATIC, TRADING_HUB, INDUSTRIAL, BLACK_MARKET, RESEARCH_FACILITY, MILITARY_BASE, SURVEILLANCE_OUTPOST, EXPLORATION_OUTPOST, MINERAL_DEPOSITS, COMMON_METAL_DEPOSITS, PRECIOUS_METAL_DEPOSITS, RARE_METAL_DEPOSITS, METHANE_POOLS, ICE_CRYSTALS, EXPLOSIVE_GASES, STRONG_MAGNETOSPHERE, VIBRANT_AURORAS, SALT_FLATS, CANYONS, PERPETUAL_DAYLIGHT, PERPETUAL_OVERCAST, DRY_SEABEDS, MAGMA_SEAS, SUPERVOLCANOES, ASH_CLOUDS, VAST_RUINS, MUTATED_FLORA, TERRAFORMED, EXTREME_TEMPERATURES, EXTREME_PRESSURE, DIVERSE_LIFE, SCARCE_LIFE, FOSSILS, WEAK_GRAVITY, STRONG_GRAVITY, CRUSHING_GRAVITY, TOXIC_ATMOSPHERE, CORROSIVE_ATMOSPHERE, BREATHABLE_ATMOSPHERE, THIN_ATMOSPHERE, JOVIAN, ROCKY, VOLCANIC, FROZEN, SWAMP, BARREN, TEMPERATE, JUNGLE, OCEAN, RADIOACTIVE, MICRO_GRAVITY_ANOMALIES, DEBRIS_CLUSTER, DEEP_CRATERS, SHALLOW_CRATERS, UNSTABLE_COMPOSITION, HOLLOWED_INTERIOR, STRIPPED, }; pub const Modifier = struct { symbol: ModSymbol, name: []const u8, description: []const u8, pub const ModSymbol = enum { STRIPPED, UNSTABLE, RADIATION_LEAK, CRITICAL_LIMIT, CIVIL_UNREST, }; }; pub const Chart = struct { waypointSymbol: Symbol, submittedBy: []const u8, submittedOn: []const u8, }; }; pub const WaypointPreview = struct { symbol: Symbol, type: Waypoint.Type, x: i64, y: i64, orbitals: []m.SymbolWrapper(Symbol) = &.{}, orbits: ?Symbol = null, pub fn prettyInline( this: *const @This(), comptime ctx: prettym.Context, run: *const prettym.Runtime, ) error{WriteFailed}!void { run.setColor(ctx, .value); try run.print("{f}", .{this.symbol}); run.setColor(ctx, .dim); try run.print("[{s}]({}, {}) ", .{ @tagName(this.type), this.x, this.y }); run.resetColor(); } }; pub const ConstructionSite = struct { symbol: Symbol, isComplete: bool, materials: []Material, pub const Material = struct { tradeSymbol: m.inventory.AllItems.Combined, required: i64, fulfilled: i64, }; }; pub const Market = struct { symbol: Symbol, exports: []m.inventory.Item = &.{}, imports: []m.inventory.Item = &.{}, exchange: []m.inventory.Item = &.{}, transactions: ?[]Transaction = null, tradeGoods: ?[]TradeGood = null, pub const Transaction = struct { waypointSymbol: Symbol, shipSymbol: []const u8, tradeSymbol: []const u8, type: Type, units: u64, pricePerUnit: u64, totalPrice: u64, timestamp: []const u8, pub const Type = enum { PURCHASE, SELL }; }; pub const TradeGood = struct { symbol: m.inventory.AllItems.Combined, type: TradeGood.Type, tradeVolume: u64, supply: Supply, activity: ?Activity = null, purchasePrice: u64, sellPrice: u64, pub const Type = enum { EXPORT, IMPORT, EXCHANGE }; }; pub const Supply = enum { SCARCE, LIMITED, MODERATE, HIGH, ABUNDANT }; pub const Activity = enum { WEAK, GROWING, STRONG, RESTRICTED }; }; pub const JumpGate = struct { symbol: Symbol, connections: []Symbol, }; pub const Shipyard = struct { symbol: Symbol, shipTypes: struct { type: m.ships.Type }, transactions: []Transaction, modificationsFee: i64, pub const Transaction = struct { waypointSymbol: Symbol, shipType: m.ships.Type, price: u64, agentSymbol: []const u8, timestamp: []const u8, }; pub const Ship = struct { activity: Market.Activity, supply: Market.Supply, purchasePrice: u64, type: m.ships.Type, name: []const u8, description: []const u8, crew: m.ships.Crew, frame: m.ships.Frame, reactor: m.ships.Reactor, engine: m.ships.Engine, modules: []m.ships.Module, mounts: []m.ships.Mount, }; }; pub const Faction = m.SymbolWrapper(m.factions.Symbol);