瀏覽代碼

feat: import from pokemon/300c7bd1ee37e25c62dc00344016bf85fd7367ba

Sam Jaffe 2 年之前
父節點
當前提交
e276d8d915

+ 18 - 0
.gitmodules

@@ -0,0 +1,18 @@
+[submodule "external/serializer"]
+	path = external/serializer
+	url = ssh://git@gogs.sjaffe.name:3000/sjjaffe/cpp-stateful-serializer.git
+[submodule "external/expect"]
+	path = external/expect
+	url = ssh://git@gogs.sjaffe.name:3000/sjjaffe/cpp-expect.git
+[submodule "external/string-utils"]
+	path = external/string-utils
+	url = ssh://git@gogs.sjaffe.name:3000/sjjaffe/cpp-string-utils.git
+[submodule "external/reflection"]
+	path = external/reflection
+	url = ssh://git@gogs.sjaffe.name:3000/sjjaffe/cpp-reflection.git
+[submodule "external/shared_random_generator"]
+	path = external/shared_random_generator
+	url = ssh://git@gogs.sjaffe.name:3000/sjjaffe/cpp-shared-random-generator.git
+[submodule "external/magic_enum"]
+	path = external/magic_enum
+	url = https://github.com/Neargye/magic_enum.git

+ 525 - 0
engine.xcodeproj/project.pbxproj

@@ -0,0 +1,525 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 55;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		CD592BED29C2A422009AC14E /* universe.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD592BEB29C2A422009AC14E /* universe.cxx */; };
+		CDD4759429C4B7A200BDB829 /* config.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDD4759129C4B7A200BDB829 /* config.cxx */; };
+		CDD4759529C4B7A200BDB829 /* event.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDD4759229C4B7A200BDB829 /* event.cxx */; };
+		CDD4759629C4B7A200BDB829 /* condition.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDD4759329C4B7A200BDB829 /* condition.cxx */; };
+		CDD4759A29C4BB0C00BDB829 /* event.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD4759729C4BB0C00BDB829 /* event.h */; };
+		CDD4759B29C4BB0C00BDB829 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD4759829C4BB0C00BDB829 /* config.h */; };
+		CDD4759C29C4BB0C00BDB829 /* condition.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD4759929C4BB0C00BDB829 /* condition.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		CDD475A329C4CDB500BDB829 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDD4759D29C4CDB500BDB829 /* shared_random_generator.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CDED6A4221B2F5A700AB91D0;
+			remoteInfo = shared_random_generator;
+		};
+		CDD475A529C4CDB500BDB829 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDD4759D29C4CDB500BDB829 /* shared_random_generator.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CD89E51324E6F3FD008167A8;
+			remoteInfo = "shared_random_generator-test";
+		};
+		CDD475AD29C4CDBA00BDB829 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDD475A729C4CDBA00BDB829 /* string-utils.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CD266862252FF4B600B3E667;
+			remoteInfo = "string-utils";
+		};
+		CDD475AF29C4CDBA00BDB829 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDD475A729C4CDBA00BDB829 /* string-utils.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CD266886252FFAAE00B3E667;
+			remoteInfo = "string_utils-test";
+		};
+		CDD475B829C4CDBF00BDB829 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDD475B129C4CDBF00BDB829 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05818F861A685AEA0072A469;
+			remoteInfo = GoogleMock;
+		};
+		CDD475BA29C4CDBF00BDB829 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDD475B129C4CDBF00BDB829 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05E96ABD1A68600C00204102;
+			remoteInfo = gmock;
+		};
+		CDD475BC29C4CDBF00BDB829 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDD475B129C4CDBF00BDB829 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05E96B1F1A68634900204102;
+			remoteInfo = gtest;
+		};
+		CDD475BE29C4CDBF00BDB829 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDD475B129C4CDBF00BDB829 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05818F901A685AEA0072A469;
+			remoteInfo = GoogleMockTests;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		CD592BDB29C2A399009AC14E /* libengine.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libengine.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		CD592BE529C2A3E0009AC14E /* engine */ = {isa = PBXFileReference; lastKnownFileType = folder; name = engine; path = include/engine; sourceTree = "<group>"; };
+		CD592BEB29C2A422009AC14E /* universe.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = universe.cxx; sourceTree = "<group>"; };
+		CD592BF029C2A462009AC14E /* universe.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = universe.h; sourceTree = "<group>"; };
+		CD592BF229C2A506009AC14E /* forwards.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = forwards.h; sourceTree = "<group>"; };
+		CD592BF329C2A531009AC14E /* universe.tpp */ = {isa = PBXFileReference; lastKnownFileType = text; path = universe.tpp; sourceTree = "<group>"; };
+		CD592C0E29C3D1E7009AC14E /* mailbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mailbox.h; sourceTree = "<group>"; };
+		CDD4759129C4B7A200BDB829 /* config.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = config.cxx; sourceTree = "<group>"; };
+		CDD4759229C4B7A200BDB829 /* event.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = event.cxx; sourceTree = "<group>"; };
+		CDD4759329C4B7A200BDB829 /* condition.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = condition.cxx; sourceTree = "<group>"; };
+		CDD4759729C4BB0C00BDB829 /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = "<group>"; };
+		CDD4759829C4BB0C00BDB829 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
+		CDD4759929C4BB0C00BDB829 /* condition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = condition.h; sourceTree = "<group>"; };
+		CDD4759D29C4CDB500BDB829 /* shared_random_generator.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = shared_random_generator.xcodeproj; path = external/shared_random_generator/shared_random_generator.xcodeproj; sourceTree = "<group>"; };
+		CDD475A729C4CDBA00BDB829 /* string-utils.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "string-utils.xcodeproj"; path = "external/string-utils/string-utils.xcodeproj"; sourceTree = "<group>"; };
+		CDD475B129C4CDBF00BDB829 /* GoogleMock.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GoogleMock.xcodeproj; path = "../../../gmock-xcode-master/GoogleMock.xcodeproj"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		CD592BD929C2A399009AC14E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		CD592BD229C2A399009AC14E = {
+			isa = PBXGroup;
+			children = (
+				CDD475B129C4CDBF00BDB829 /* GoogleMock.xcodeproj */,
+				CDD475A729C4CDBA00BDB829 /* string-utils.xcodeproj */,
+				CDD4759D29C4CDB500BDB829 /* shared_random_generator.xcodeproj */,
+				CD592BE529C2A3E0009AC14E /* engine */,
+				CD592BE229C2A3C8009AC14E /* include */,
+				CD592BE429C2A3C8009AC14E /* src */,
+				CD592BE329C2A3C8009AC14E /* test */,
+				CD592BDC29C2A399009AC14E /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		CD592BDC29C2A399009AC14E /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CD592BDB29C2A399009AC14E /* libengine.a */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CD592BE229C2A3C8009AC14E /* include */ = {
+			isa = PBXGroup;
+			children = (
+				CD592BEF29C2A462009AC14E /* engine */,
+			);
+			path = include;
+			sourceTree = "<group>";
+		};
+		CD592BE329C2A3C8009AC14E /* test */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			path = test;
+			sourceTree = "<group>";
+		};
+		CD592BE429C2A3C8009AC14E /* src */ = {
+			isa = PBXGroup;
+			children = (
+				CDD4759329C4B7A200BDB829 /* condition.cxx */,
+				CDD4759129C4B7A200BDB829 /* config.cxx */,
+				CDD4759229C4B7A200BDB829 /* event.cxx */,
+				CD592BEB29C2A422009AC14E /* universe.cxx */,
+			);
+			path = src;
+			sourceTree = "<group>";
+		};
+		CD592BEF29C2A462009AC14E /* engine */ = {
+			isa = PBXGroup;
+			children = (
+				CDD4759929C4BB0C00BDB829 /* condition.h */,
+				CDD4759829C4BB0C00BDB829 /* config.h */,
+				CDD4759729C4BB0C00BDB829 /* event.h */,
+				CD592BF229C2A506009AC14E /* forwards.h */,
+				CD592C0E29C3D1E7009AC14E /* mailbox.h */,
+				CD592BF029C2A462009AC14E /* universe.h */,
+				CD592BF329C2A531009AC14E /* universe.tpp */,
+			);
+			path = engine;
+			sourceTree = "<group>";
+		};
+		CDD4759E29C4CDB500BDB829 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CDD475A429C4CDB500BDB829 /* libshared_random_generator.dylib */,
+				CDD475A629C4CDB500BDB829 /* shared_random_generator-test.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CDD475A829C4CDBA00BDB829 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CDD475AE29C4CDBA00BDB829 /* libstring-utils.a */,
+				CDD475B029C4CDBA00BDB829 /* string_utils-test.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CDD475B229C4CDBF00BDB829 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CDD475B929C4CDBF00BDB829 /* GoogleMock.framework */,
+				CDD475BB29C4CDBF00BDB829 /* gmock.framework */,
+				CDD475BD29C4CDBF00BDB829 /* gtest.framework */,
+				CDD475BF29C4CDBF00BDB829 /* GoogleMockTests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		CD592BD729C2A399009AC14E /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CDD4759B29C4BB0C00BDB829 /* config.h in Headers */,
+				CDD4759A29C4BB0C00BDB829 /* event.h in Headers */,
+				CDD4759C29C4BB0C00BDB829 /* condition.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		CD592BDA29C2A399009AC14E /* engine */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CD592BDF29C2A399009AC14E /* Build configuration list for PBXNativeTarget "engine" */;
+			buildPhases = (
+				CD592BD729C2A399009AC14E /* Headers */,
+				CD592BD829C2A399009AC14E /* Sources */,
+				CD592BD929C2A399009AC14E /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = engine;
+			productName = engine_base;
+			productReference = CD592BDB29C2A399009AC14E /* libengine.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		CD592BD329C2A399009AC14E /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				BuildIndependentTargetsInParallel = 1;
+				LastUpgradeCheck = 1340;
+				TargetAttributes = {
+					CD592BDA29C2A399009AC14E = {
+						CreatedOnToolsVersion = 13.4.1;
+					};
+				};
+			};
+			buildConfigurationList = CD592BD629C2A399009AC14E /* Build configuration list for PBXProject "engine" */;
+			compatibilityVersion = "Xcode 13.0";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = CD592BD229C2A399009AC14E;
+			productRefGroup = CD592BDC29C2A399009AC14E /* Products */;
+			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = CDD475B229C4CDBF00BDB829 /* Products */;
+					ProjectRef = CDD475B129C4CDBF00BDB829 /* GoogleMock.xcodeproj */;
+				},
+				{
+					ProductGroup = CDD4759E29C4CDB500BDB829 /* Products */;
+					ProjectRef = CDD4759D29C4CDB500BDB829 /* shared_random_generator.xcodeproj */;
+				},
+				{
+					ProductGroup = CDD475A829C4CDBA00BDB829 /* Products */;
+					ProjectRef = CDD475A729C4CDBA00BDB829 /* string-utils.xcodeproj */;
+				},
+			);
+			projectRoot = "";
+			targets = (
+				CD592BDA29C2A399009AC14E /* engine */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+		CDD475A429C4CDB500BDB829 /* libshared_random_generator.dylib */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.dylib";
+			path = libshared_random_generator.dylib;
+			remoteRef = CDD475A329C4CDB500BDB829 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDD475A629C4CDB500BDB829 /* shared_random_generator-test.xctest */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.cfbundle;
+			path = "shared_random_generator-test.xctest";
+			remoteRef = CDD475A529C4CDB500BDB829 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDD475AE29C4CDBA00BDB829 /* libstring-utils.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libstring-utils.a";
+			remoteRef = CDD475AD29C4CDBA00BDB829 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDD475B029C4CDBA00BDB829 /* string_utils-test.xctest */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.cfbundle;
+			path = "string_utils-test.xctest";
+			remoteRef = CDD475AF29C4CDBA00BDB829 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDD475B929C4CDBF00BDB829 /* GoogleMock.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = GoogleMock.framework;
+			remoteRef = CDD475B829C4CDBF00BDB829 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDD475BB29C4CDBF00BDB829 /* gmock.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = gmock.framework;
+			remoteRef = CDD475BA29C4CDBF00BDB829 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDD475BD29C4CDBF00BDB829 /* gtest.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = gtest.framework;
+			remoteRef = CDD475BC29C4CDBF00BDB829 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDD475BF29C4CDBF00BDB829 /* GoogleMockTests.xctest */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.cfbundle;
+			path = GoogleMockTests.xctest;
+			remoteRef = CDD475BE29C4CDBF00BDB829 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CD592BD829C2A399009AC14E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD592BED29C2A422009AC14E /* universe.cxx in Sources */,
+				CDD4759629C4B7A200BDB829 /* condition.cxx in Sources */,
+				CDD4759529C4B7A200BDB829 /* event.cxx in Sources */,
+				CDD4759429C4B7A200BDB829 /* config.cxx in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		CD592BDD29C2A399009AC14E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 12.0;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+				SYSTEM_HEADER_SEARCH_PATHS = (
+					/opt/local/include,
+					"$(PROJECT_DIR)/include",
+					"$(PROJECT_DIR)/external/expect/include",
+					"$(PROJECT_DIR)/external/magic_enum/include",
+					"$(PROJECT_DIR)/external/reflection/include",
+					"$(PROJECT_DIR)/external/serializer/include",
+					"$(PROJECT_DIR)/external/shared_random_generator/include",
+					"$(PROJECT_DIR)/external/string-utils/include",
+				);
+			};
+			name = Debug;
+		};
+		CD592BDE29C2A399009AC14E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 12.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = macosx;
+				SYSTEM_HEADER_SEARCH_PATHS = (
+					/opt/local/include,
+					"$(PROJECT_DIR)/include",
+					"$(PROJECT_DIR)/external/expect/include",
+					"$(PROJECT_DIR)/external/magic_enum/include",
+					"$(PROJECT_DIR)/external/reflection/include",
+					"$(PROJECT_DIR)/external/serializer/include",
+					"$(PROJECT_DIR)/external/shared_random_generator/include",
+					"$(PROJECT_DIR)/external/string-utils/include",
+				);
+			};
+			name = Release;
+		};
+		CD592BE029C2A399009AC14E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				EXECUTABLE_PREFIX = lib;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		CD592BE129C2A399009AC14E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				EXECUTABLE_PREFIX = lib;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		CD592BD629C2A399009AC14E /* Build configuration list for PBXProject "engine" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD592BDD29C2A399009AC14E /* Debug */,
+				CD592BDE29C2A399009AC14E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CD592BDF29C2A399009AC14E /* Build configuration list for PBXNativeTarget "engine" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD592BE029C2A399009AC14E /* Debug */,
+				CD592BE129C2A399009AC14E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = CD592BD329C2A399009AC14E /* Project object */;
+}

+ 67 - 0
engine.xcodeproj/xcshareddata/xcschemes/engine.xcscheme

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1340"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "CD592BDA29C2A399009AC14E"
+               BuildableName = "libengine.a"
+               BlueprintName = "engine"
+               ReferencedContainer = "container:engine.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "CD592BDA29C2A399009AC14E"
+            BuildableName = "libengine.a"
+            BlueprintName = "engine"
+            ReferencedContainer = "container:engine.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 1 - 0
external/expect

@@ -0,0 +1 @@
+Subproject commit f096edddd9d8eb2ba07c2dd7ec385500c0576214

+ 1 - 0
external/magic_enum

@@ -0,0 +1 @@
+Subproject commit e1a68e9dd3d2e9180b04c8aeacd4975db745e6b8

+ 1 - 0
external/reflection

@@ -0,0 +1 @@
+Subproject commit 55d120ac81d4bf0c0377b6e704f8391e37b0cadb

+ 1 - 0
external/serializer

@@ -0,0 +1 @@
+Subproject commit 37078d681324582098c84b71f26aa671f20b0f47

+ 1 - 0
external/shared_random_generator

@@ -0,0 +1 @@
+Subproject commit 46fd7798ed7cf9ade815018df5d93dc2b2b1c4a3

+ 1 - 0
external/string-utils

@@ -0,0 +1 @@
+Subproject commit bf98bd04e6dfa3a60c354d58ba453265b0d2e121

+ 43 - 0
include/engine/condition.h

@@ -0,0 +1,43 @@
+//
+//  condition.hpp
+//  pokemon-engine
+//
+//  Created by Sam Jaffe on 7/6/22.
+//  Copyright © 2022 Sam Jaffe. All rights reserved.
+//
+
+#pragma once
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <reflection/forward.h>
+#include <reflection/property.h>
+
+#include <engine/forwards.h>
+
+namespace engine {
+
+class Condition {
+public:
+  using Predicate = std::function<bool(engine::Event const &)>;
+  enum class Comparator { NOT_EQUAL = 0, EQUAL = 1, LESS = 2, GREATER = 4 };
+
+private:
+  std::string event_type_;
+  std::vector<Predicate> predicates_;
+
+public:
+  Condition() = default;
+  Condition(std::string event_type, std::vector<Predicate> predicates);
+
+  std::string_view event_type() const { return event_type_; }
+  bool operator()(Event const & on) const;
+
+  template <typename T>
+  static Predicate make_predicate(reflection::Property const & scope,
+                                  Comparator cmp, T const & value);
+};
+
+}

+ 67 - 0
include/engine/config.h

@@ -0,0 +1,67 @@
+//
+//  config.h
+//  pokemon-engine
+//
+//  Created by Sam Jaffe on 12/22/18.
+//  Copyright © 2018 Sam Jaffe. All rights reserved.
+//
+
+#pragma once
+
+#include <filesystem>
+#include <map>
+#include <memory>
+#include <string>
+
+#include <json/forwards.h>
+
+namespace engine::env {
+class Config {
+private:
+  std::filesystem::path config_path_{""};
+  std::filesystem::path resource_path_;
+  std::map<std::string, std::string> properties_;
+
+public:
+  /**
+   * @brief Load this configuration from a JSON file on disk.
+   * @param filepath The absolute path to a JSON config file.
+   * @throws std::logic_error if any of the following:
+   * - filepath is empty (i.e. Config cfg = Config("");)
+   * - filepath is not an absolute UNIX-style path
+   * - The file is readable and exists.
+   */
+  Config(std::filesystem::path const & filepath);
+  ~Config();
+
+  /**
+   * @brief Obtain the absolute path to a resource, as determined by the
+   * properties loaded into this object. For example,
+   * @code std::string image_path = cfg.resource("sprites/nurse_joy.png");
+   * @param rel_path The relative path to the resource file we are searching
+   * for.
+   * @return The absolute path to the file
+   */
+  std::filesystem::path resource(std::filesystem::path const & rel_path) const;
+
+  /**
+   * @brief Fetch a singluar property that exists within the object
+   * @param name The property name being fetched
+   * @param fallback A fallback value in case that the object is absent
+   * @return The property being read in
+   */
+  std::string const & property(std::string const & name,
+                               std::string const & fallback) const;
+
+protected:
+  /**
+   * @brief Construct a config from a raw json blob. Primarily for testing.
+   * @param json A json object containing certain properties
+   */
+  Config(Json::Value const & json,
+         std::filesystem::path const & config_path = "");
+
+private:
+  std::filesystem::path fix(std::filesystem::path input) const;
+};
+}

+ 31 - 0
include/engine/event.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include <cstdlib>
+#include <string>
+
+#include <reflection/context.h>
+#include <reflection/object.h>
+
+#include <engine/forwards.h>
+
+namespace engine {
+
+class Event {
+private:
+  uint64_t id_;
+  std::string_view type_;
+  reflection::Object source_;
+  reflection::Context context_;
+
+public:
+  Event(std::string_view type, reflection::Object const & source,
+        reflection::Context const & context);
+
+  bool is_a(std::string_view type) const { return type_ == type; }
+  std::string_view type() const { return type_; }
+
+  reflection::Object const & source() const { return source_; }
+  reflection::Context const & context() const { return context_; }
+};
+
+}

+ 26 - 0
include/engine/forwards.h

@@ -0,0 +1,26 @@
+//
+//  forwards.h
+//  engine_base
+//
+//  Created by Sam Jaffe on 3/15/23.
+//
+
+#pragma once
+
+#include <serializer/forwards.h>
+
+namespace engine {
+class Condition;
+class Event;
+class Mailbox;
+class Universe;
+class random_number_generator;
+}
+
+namespace engine::detail {
+class random_impl;
+}
+
+namespace engine::env {
+class Config;
+}

+ 33 - 0
include/engine/mailbox.h

@@ -0,0 +1,33 @@
+//
+//  mailbox.h
+//  engine
+//
+//  Created by Sam Jaffe on 3/16/23.
+//
+
+#pragma once
+
+#include <string>
+
+#include <serializer/stringizer.h>
+
+namespace engine {
+/**
+ * @brief A generic mailbox class that contains a system to message
+ */
+class Mailbox {
+public:
+  virtual ~Mailbox() = default;
+  virtual void notify(std::string const & str) = 0;
+  template <typename... Args> void notifyf(Args &&... args);
+
+private:
+};
+
+template <typename... Args> void Mailbox::notifyf(Args &&... args) {
+  std::string str;
+  using ::serializer::to_string;
+  (str.append(to_string(std::forward<Args>(args))), ...);
+  notify(str);
+}
+}

+ 56 - 0
include/engine/universe.h

@@ -0,0 +1,56 @@
+//
+//  universe.h
+//  engine_base
+//
+//  Created by Sam Jaffe on 3/15/23.
+//
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <engine/forwards.h>
+
+namespace engine {
+class Universe {
+private:
+  std::shared_ptr<Mailbox> mailbox_;
+  // The universe is not a shared object, so by convention we use unique_ptr
+  // to store everything that does not need to be shared.
+  std::unique_ptr<env::Config> config_;
+  std::unique_ptr<random_number_generator> random_;
+  // The cache is, by definition, a shared object and so uses shared_ptr
+  std::shared_ptr<serializer::SharedCache> serialcache_;
+  std::unique_ptr<serializer::Jsonizer> jsonizer_;
+
+public:
+  Mailbox & mailbox() const { return *mailbox_; }
+  env::Config const & config() const { return *config_; }
+  serializer::Jsonizer & jsonizer() const { return *jsonizer_; }
+  random_number_generator const & random() const { return *random_; }
+
+  /**
+   * @brief Construct a universe with all necessary components
+   * @param cfg The config object generated from reading a config file or JSON
+   * @param rng A random number generator's underlying implementation. This
+   * exists for dependency injection's sake. If rng is null, then random_ will
+   * be constructed with the default random device.
+   */
+  Universe(std::shared_ptr<Mailbox> mailbox, env::Config const & cfg,
+           std::shared_ptr<detail::random_impl> rng);
+  ~Universe();
+
+protected:
+  template <typename T>
+  void load(std::string const & name, std::string const & fallback = "");
+
+  /**
+   * @deprecated This exists solely for the purpose of needing to initialize
+   * the singleton.
+   */
+  Universe();
+  Universe(Universe &&) = default;
+  Universe & operator=(Universe &&) = default;
+};
+}

+ 43 - 0
include/engine/universe.tpp

@@ -0,0 +1,43 @@
+//
+//  universe.tpp
+//  engine_base
+//
+//  Created by Sam Jaffe on 3/15/23.
+//
+
+#pragma once
+
+#include <filesystem>
+#include <fstream>
+
+#include <json/json.h>
+
+#include <engine/universe.h>
+
+namespace engine {
+template <typename T>
+void Universe::load(std::string const & name, std::string const & fallback) {
+  std::filesystem::path location = config().property(name, fallback);
+  if (!std::filesystem::exists(location)) { return; }
+
+  auto import = [this](auto & file) {
+    Json::Value json;
+    std::ifstream in(file.string());
+    in >> json;
+    std::shared_ptr<T const> tmp;
+    if (json.isArray()) {
+      for (Json::Value const & elm : json) {
+        jsonizer().from_json(tmp, elm);
+      }
+    } else {
+      jsonizer().from_json(tmp, json);
+    }
+  };
+
+  if (std::filesystem::is_directory(location)) {
+    std::for_each(std::filesystem::directory_iterator(location), {}, import);
+  } else {
+    import(location);
+  }
+}
+}

+ 61 - 0
src/condition.cxx

@@ -0,0 +1,61 @@
+//
+//  condition.cxx
+//  pokemon-engine
+//
+//  Created by Sam Jaffe on 7/6/22.
+//  Copyright © 2022 Sam Jaffe. All rights reserved.
+//
+
+#include <engine/condition.h>
+
+#include <string>
+
+#include <expect/expect.hpp>
+#include <reflection/context.h>
+#include <string_utils/tokenizer.h>
+
+#include <engine/event.h>
+
+#define DEFINE_MAKE_PREDICATE(T)                                               \
+  template Condition::Predicate Condition::make_predicate(                     \
+      reflection::Property const &, Comparator, T const &)
+
+namespace engine {
+
+Condition::Condition(std::string event_type, std::vector<Predicate> predicates)
+    : event_type_(std::move(event_type)), predicates_(std::move(predicates)) {}
+
+bool Condition::operator()(Event const & on) const {
+  return on.type() == event_type_ &&
+         std::all_of(predicates_.begin(), predicates_.end(),
+                     [&](auto & pred) { return pred(on); });
+}
+
+template <typename T>
+Condition::Predicate
+Condition::make_predicate(reflection::Property const & scope, Comparator cmp,
+                          T const & value) {
+  using C = Comparator;
+  using namespace magic_enum::bitwise_operators;
+
+  // Replace zero Comparator with bitwise not equals
+  if (cmp == C::NOT_EQUAL) { cmp = C::LESS | C::GREATER; }
+  // Prohibit tautologies
+  expects(cmp < (C::EQUAL | C::LESS | C::GREATER),
+          "cannot use all states in Comparitor");
+
+  return [=](engine::Event const & event) {
+    T const & state(event.context().get(scope));
+    if (state == value) {
+      return static_cast<bool>(cmp & C::EQUAL);
+    } else if (state < value) {
+      return static_cast<bool>(cmp & C::LESS);
+    } else {
+      return static_cast<bool>(cmp & C::GREATER);
+    }
+  };
+}
+
+DEFINE_MAKE_PREDICATE(int);
+DEFINE_MAKE_PREDICATE(std::string);
+}

+ 63 - 0
src/config.cxx

@@ -0,0 +1,63 @@
+//
+//  config.cxx
+//  pokemon-engine
+//
+//  Created by Sam Jaffe on 12/22/18.
+//  Copyright © 2018 Sam Jaffe. All rights reserved.
+//
+
+#include <engine/config.h>
+
+#include <filesystem>
+#include <fstream>
+
+#include <expect/expect.hpp>
+#include <json/json.h>
+
+#include <serializer/jsonizer.tpp>
+
+namespace {
+Json::Value read(std::filesystem::path const & file) {
+  namespace fs = std::filesystem;
+  // Ensure that the file we are reading is valid
+  expects(file.is_absolute());
+  expects(fs::exists(file) && fs::is_regular_file(file));
+  std::ifstream in(file.string());
+  expects(in.good(), "Cannot read file " + file.string());
+
+  // Read the file
+  Json::Reader reader;
+  Json::Value json;
+  ensures(reader.parse(in, json), reader.getFormattedErrorMessages());
+  return json;
+}
+}
+
+namespace engine::env {
+Config::Config(std::filesystem::path const & file)
+    : Config(read(file), file.parent_path()) {}
+
+Config::Config(Json::Value const & json,
+               std::filesystem::path const & config_path)
+    : config_path_(config_path),
+      resource_path_(fix(json["resource_path"].asString())) {
+  auto const & props = json["properties"];
+  for (auto it = props.begin(), end = props.end(); it != end; ++it) {
+    properties_.emplace(it.name(), fix(it->asString()).string());
+  }
+}
+
+Config::~Config() {}
+
+std::filesystem::path
+Config::resource(std::filesystem::path const & rel_path) const {
+  return resource_path_ / rel_path;
+}
+
+std::string const & Config::property(std::string const & name,
+                                     std::string const & fallback) const {
+  auto it = properties_.find(name);
+  return it != properties_.end() ? it->second : fallback;
+}
+
+}

+ 27 - 0
src/event.cxx

@@ -0,0 +1,27 @@
+//
+//  event.cxx
+//  pokemon-engine
+//
+//  Created by Sam Jaffe on 6/18/22.
+//  Copyright © 2022 Sam Jaffe. All rights reserved.
+//
+
+#include <engine/event.h>
+
+#include <atomic>
+#include <functional>
+#include <string>
+#include <utility>
+
+namespace engine {
+
+static uint64_t next_id() {
+  static std::atomic<uint64_t> value_{0};
+  return value_.fetch_add(1);
+}
+
+Event::Event(std::string_view type, reflection::Object const & source,
+             reflection::Context const & context)
+    : id_(next_id()), type_(type), source_(source), context_(context) {}
+
+}

+ 30 - 0
src/universe.cxx

@@ -0,0 +1,30 @@
+//
+//  universe.cxx
+//  engine_base
+//
+//  Created by Sam Jaffe on 3/15/23.
+//
+
+#include <engine/universe.h>
+
+#include <serializer/jsonizer.tpp>
+#include <serializer/shared_cache.h>
+#include <shared_random_generator/random.h>
+
+#include <engine/config.h>
+
+namespace engine {
+
+Universe::Universe(std::shared_ptr<::engine::Mailbox> mailbox,
+                   env::Config const & cfg,
+                   std::shared_ptr<detail::random_impl> rng)
+    : mailbox_(mailbox), config_(std::make_unique<env::Config>(cfg)),
+      random_(rng ? std::make_unique<random_number_generator>(rng)
+                  : std::make_unique<random_number_generator>()),
+      serialcache_(std::make_shared<serializer::SharedCache>()),
+      jsonizer_(std::make_unique<serializer::Jsonizer>(serialcache_)) {}
+
+Universe::Universe() {}
+Universe::~Universe() {}
+
+}