Great big lump o' stuff to deal with ship types and related things more cleanly.
OOShipRegistry parses shipdata.plist, shipyard.plist, demoships.plist and new shipdata-overrides.plist and shipyard-overrides.plist, resolves like_ship inheritance, does some sanity checking, filters out various sorts of invalid shipdata and shipyard entries and manages role->ship key mapping with probability weighting. The latter is managed by OOProbabilitySet, which should probably be used by OORoleSet and OOProbabilisticTextureManager too. OOProbabilitySet is O(log n) for random selection instead of O(n) like the current linear-search code. The next step is to start using OOShipRegistry everywhere. git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@1607 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
parent
edf000ec1d
commit
30bce0b115
@ -26,7 +26,7 @@ endif
|
||||
OBJC_PROGRAM_NAME = oolite
|
||||
|
||||
oolite_C_FILES = legacy_random.c strlcpy.c OOTCPStreamDecoder.c
|
||||
oolite_OBJC_FILES = OOCocoa.m Comparison.m AI.m DustEntity.m Entity.m GameController.m GuiDisplayGen.m HeadUpDisplay.m main.m MyOpenGLView.m OpenGLSprite.m ParticleEntity.m PlanetEntity.m PlayerEntityLegacyScriptEngine.m PlayerEntityContracts.m PlayerEntityControls.m PlayerEntityLoadSave.m PlayerEntitySound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntityAI.m ShipEntity.m SkyEntity.m StationEntity.m Universe.m OOSound.m SDLMusic.m NSFileManagerOOExtensions.m JoystickHandler.m PlayerEntityStickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m NSScannerOOExtensions.m OOXMLExtensions.m NSMutableDictionaryOOExtensions.m Geometry.m Octree.m CollisionRegion.m OOColor.m OOLogging.m OOCacheManager.m OOCache.m OOStringParsing.m OOCollectionExtractors.m OOVector.m OOMatrix.m OOQuaternion.m OOVoxel.m OOTriangle.m OOPListParsing.m OOFastArithmetic.m OOTextureScaling.m OOConstToString.m OOScript.m OOJSScript.m OOJavaScriptEngine.m OOPListScript.m NSStringOOExtensions.m PlayerEntityScriptMethods.m OOWeakReference.m OOJSEntity.m EntityOOJavaScriptExtensions.m OOJSQuaternion.m OOMaterial.m OOShaderMaterial.m OOShaderProgram.m OOShaderUniform.m OOTexture.m OOTextureLoader.m OOPNGTextureLoader.m OOOpenGLExtensionManager.m OOBasicMaterial.m OOSingleTextureMaterial.m OOCPUInfo.m OOSelfDrawingEntity.m OOEntityWithDrawable.m OODrawable.m OOJSVector.m OOMesh.m OOOpenGL.m OOGraphicsResetManager.m OOProbabilisticTextureManager.m OODebugGLDrawing.m OOShaderUniformMethodType.m OOAsyncQueue.m TextureStore.m OOOXPVerifier.m OOOXPVerifierStage.m OOFileScannerVerifierStage.m OOCheckRequiresPListVerifierStage.m OOCheckDemoShipsPListVerifierStage.m OOCheckEquipmentPListVerifierStage.m OOTextureVerifierStage.m OOModelVerifierStage.m OOCheckShipDataPListVerifierStage.m OOPListSchemaVerifier.m OOJSShip.m OOJSPlayer.m OOJSCall.m OOJSStation.m OOJSSystem.m OOLegacyEventHandlerScript.m OOJSOolite.m OORoleSet.m OOJSGlobal.m OOJSMissionVariables.m OOJSMission.m OOPriorityQueue.m OOScriptTimer.m OOJSTimer.m OOJSClock.m OODebugSupport.m OODebugMonitor.m OOJSConsole.m OODebugTCPConsoleClient.m OOTCPStreamDecoderAbstractionLayer.m OOEntityFilterPredicate.m OOJSPlanet.m OOJSWorldScripts.m OOJSSun.m NSThreadOOExtensions.m OOEncodingConverter.m OOJSSound.m OOJSSoundSource.m OOMusicController.m OOLogHeader.m OOJSSpecialFunctions.m OOSpatialReference.m OOSkyDrawable.m OOFilteringEnumerator.m OOSoundSourcePool.m ShipEntityScriptMethods.m
|
||||
oolite_OBJC_FILES = OOCocoa.m Comparison.m AI.m DustEntity.m Entity.m GameController.m GuiDisplayGen.m HeadUpDisplay.m main.m MyOpenGLView.m OpenGLSprite.m ParticleEntity.m PlanetEntity.m PlayerEntityLegacyScriptEngine.m PlayerEntityContracts.m PlayerEntityControls.m PlayerEntityLoadSave.m PlayerEntitySound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntityAI.m ShipEntity.m SkyEntity.m StationEntity.m Universe.m OOSound.m SDLMusic.m NSFileManagerOOExtensions.m JoystickHandler.m PlayerEntityStickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m NSScannerOOExtensions.m OOXMLExtensions.m NSMutableDictionaryOOExtensions.m Geometry.m Octree.m CollisionRegion.m OOColor.m OOLogging.m OOCacheManager.m OOCache.m OOStringParsing.m OOCollectionExtractors.m OOVector.m OOMatrix.m OOQuaternion.m OOVoxel.m OOTriangle.m OOPListParsing.m OOFastArithmetic.m OOTextureScaling.m OOConstToString.m OOScript.m OOJSScript.m OOJavaScriptEngine.m OOPListScript.m NSStringOOExtensions.m PlayerEntityScriptMethods.m OOWeakReference.m OOJSEntity.m EntityOOJavaScriptExtensions.m OOJSQuaternion.m OOMaterial.m OOShaderMaterial.m OOShaderProgram.m OOShaderUniform.m OOTexture.m OOTextureLoader.m OOPNGTextureLoader.m OOOpenGLExtensionManager.m OOBasicMaterial.m OOSingleTextureMaterial.m OOCPUInfo.m OOSelfDrawingEntity.m OOEntityWithDrawable.m OODrawable.m OOJSVector.m OOMesh.m OOOpenGL.m OOGraphicsResetManager.m OOProbabilisticTextureManager.m OODebugGLDrawing.m OOShaderUniformMethodType.m OOAsyncQueue.m TextureStore.m OOOXPVerifier.m OOOXPVerifierStage.m OOFileScannerVerifierStage.m OOCheckRequiresPListVerifierStage.m OOCheckDemoShipsPListVerifierStage.m OOCheckEquipmentPListVerifierStage.m OOTextureVerifierStage.m OOModelVerifierStage.m OOCheckShipDataPListVerifierStage.m OOPListSchemaVerifier.m OOJSShip.m OOJSPlayer.m OOJSCall.m OOJSStation.m OOJSSystem.m OOLegacyEventHandlerScript.m OOJSOolite.m OORoleSet.m OOJSGlobal.m OOJSMissionVariables.m OOJSMission.m OOPriorityQueue.m OOScriptTimer.m OOJSTimer.m OOJSClock.m OODebugSupport.m OODebugMonitor.m OOJSConsole.m OODebugTCPConsoleClient.m OOTCPStreamDecoderAbstractionLayer.m OOEntityFilterPredicate.m OOJSPlanet.m OOJSWorldScripts.m OOJSSun.m NSThreadOOExtensions.m OOEncodingConverter.m OOJSSound.m OOJSSoundSource.m OOMusicController.m OOLogHeader.m OOJSSpecialFunctions.m OOSpatialReference.m OOSkyDrawable.m OOFilteringEnumerator.m OOSoundSourcePool.m ShipEntityScriptMethods.m OOShipRegistry.m OOProbabilitySet.m NSDictionaryOOExtensions.m
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/objc.make
|
||||
include GNUmakefile.postamble
|
||||
|
@ -33,6 +33,12 @@
|
||||
1A0365890D7CA05000B5F46F /* OOSkyDrawable.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A15044A0C12C50D0032F3E8 /* OOSkyDrawable.m */; };
|
||||
1A03658A0D7CA05000B5F46F /* OOSkyDrawable.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1504490C12C50D0032F3E8 /* OOSkyDrawable.h */; };
|
||||
1A03659B0D7CA0EE00B5F46F /* oolite-nebula-4.png in Copy Textures */ = {isa = PBXBuildFile; fileRef = 1A0365990D7CA0EE00B5F46F /* oolite-nebula-4.png */; };
|
||||
1A0479E90DC9F81000EE1CD0 /* OOShipRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A0479E70DC9F81000EE1CD0 /* OOShipRegistry.h */; };
|
||||
1A0479EA0DC9F81000EE1CD0 /* OOShipRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A0479E80DC9F81000EE1CD0 /* OOShipRegistry.m */; };
|
||||
1A047A450DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A047A430DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.h */; };
|
||||
1A047A460DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A047A440DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.m */; };
|
||||
1A047B7E0DCB3D7500EE1CD0 /* OOProbabilitySet.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A047B7C0DCB3D7500EE1CD0 /* OOProbabilitySet.h */; };
|
||||
1A047B7F0DCB3D7500EE1CD0 /* OOProbabilitySet.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A047B7D0DCB3D7500EE1CD0 /* OOProbabilitySet.m */; };
|
||||
1A0DA2EE0D71D280009B0970 /* OOJSSpecialFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A0DA2EC0D71D280009B0970 /* OOJSSpecialFunctions.h */; };
|
||||
1A0DA2EF0D71D280009B0970 /* OOJSSpecialFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DA2ED0D71D280009B0970 /* OOJSSpecialFunctions.m */; };
|
||||
1A1502F60C1201C30032F3E8 /* oolite-unknown-ship.dat in Copy Models */ = {isa = PBXBuildFile; fileRef = 1A1502F50C1201C30032F3E8 /* oolite-unknown-ship.dat */; };
|
||||
@ -1019,6 +1025,12 @@
|
||||
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
1A020E0A0D020AFB00C3F51E /* changedScriptHandlers.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = changedScriptHandlers.plist; sourceTree = "<group>"; };
|
||||
1A0365990D7CA0EE00B5F46F /* oolite-nebula-4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "oolite-nebula-4.png"; sourceTree = "<group>"; };
|
||||
1A0479E70DC9F81000EE1CD0 /* OOShipRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOShipRegistry.h; sourceTree = "<group>"; };
|
||||
1A0479E80DC9F81000EE1CD0 /* OOShipRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOShipRegistry.m; sourceTree = "<group>"; };
|
||||
1A047A430DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSDictionaryOOExtensions.h; sourceTree = "<group>"; };
|
||||
1A047A440DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSDictionaryOOExtensions.m; sourceTree = "<group>"; };
|
||||
1A047B7C0DCB3D7500EE1CD0 /* OOProbabilitySet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOProbabilitySet.h; sourceTree = "<group>"; };
|
||||
1A047B7D0DCB3D7500EE1CD0 /* OOProbabilitySet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOProbabilitySet.m; sourceTree = "<group>"; };
|
||||
1A0517D10C7B376700BA5CCA /* debug-exports.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = "debug-exports.exp"; sourceTree = "<group>"; };
|
||||
1A0519340C7CCAC900BA5CCA /* DebugOXP.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = DebugOXP.xcodeproj; path = "Mac-DebugOXP/DebugOXP.xcodeproj"; sourceTree = SOURCE_ROOT; };
|
||||
1A0DA2EC0D71D280009B0970 /* OOJSSpecialFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOJSSpecialFunctions.h; sourceTree = "<group>"; };
|
||||
@ -1035,7 +1047,7 @@
|
||||
1A23154F0B9C778400EF0852 /* splash.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = splash.png; sourceTree = "<group>"; };
|
||||
1A2315500B9C778400EF0852 /* splashback.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = splashback.png; sourceTree = "<group>"; };
|
||||
1A2315510B9C778400EF0852 /* trumblebox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = trumblebox.png; sourceTree = "<group>"; };
|
||||
1A2316DE0B9CFAD700EF0852 /* characters.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = characters.plist; sourceTree = "<group>"; };
|
||||
1A2316DE0B9CFAD700EF0852 /* characters.plist */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = characters.plist; sourceTree = "<group>"; };
|
||||
1A2316DF0B9CFAD700EF0852 /* commodities.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = commodities.plist; sourceTree = "<group>"; };
|
||||
1A2316E00B9CFAD700EF0852 /* customsounds.plist */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = customsounds.plist; sourceTree = "<group>"; };
|
||||
1A2316E10B9CFAD700EF0852 /* demoships.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = demoships.plist; sourceTree = "<group>"; };
|
||||
@ -1535,7 +1547,7 @@
|
||||
1ACEA7270C91DF2800C7CE97 /* OOJSMissionVariables.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOJSMissionVariables.m; sourceTree = "<group>"; };
|
||||
1ACEA7A80C91E32800C7CE97 /* OOJSMission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOJSMission.h; sourceTree = "<group>"; };
|
||||
1ACEA7A90C91E32800C7CE97 /* OOJSMission.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOJSMission.m; sourceTree = "<group>"; };
|
||||
1AD0C32F0C463FCB0070BD23 /* autoAImap.plist */ = {isa = PBXFileReference; fileEncoding = 4; languageSpecificationIdentifier = plist; lastKnownFileType = text.xml; path = autoAImap.plist; sourceTree = "<group>"; };
|
||||
1AD0C32F0C463FCB0070BD23 /* autoAImap.plist */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; languageSpecificationIdentifier = plist; path = autoAImap.plist; sourceTree = "<group>"; };
|
||||
1AD0C6C80C47B76F0070BD23 /* SCRDynamicShim.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCRDynamicShim.m; sourceTree = "<group>"; };
|
||||
1AD0C6E30C47B82C0070BD23 /* SmartCrashReportsInstall.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = SmartCrashReportsInstall.o; sourceTree = "<group>"; };
|
||||
1AD0C6E40C47B82C0070BD23 /* SmartCrashReportsInstall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmartCrashReportsInstall.h; sourceTree = "<group>"; };
|
||||
@ -2349,6 +2361,8 @@
|
||||
1AB4AEB70D688AD9003076D6 /* OOLogHeader.m */,
|
||||
25161107099544390037C2E1 /* OOXMLExtensions.h */,
|
||||
25161102099544380037C2E1 /* OOXMLExtensions.m */,
|
||||
1A047A430DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.h */,
|
||||
1A047A440DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.m */,
|
||||
1A8A37550B960337007D20B8 /* NSMutableDictionaryOOExtensions.h */,
|
||||
1A8A37540B960337007D20B8 /* NSMutableDictionaryOOExtensions.m */,
|
||||
1A8A394D0B96229C007D20B8 /* NSFileManagerOOExtensions.h */,
|
||||
@ -2390,6 +2404,8 @@
|
||||
1A1616610D7DCFDC0094AE5B /* OOFilteringEnumerator.m */,
|
||||
1ACBF06F0D82DF9B00CC005F /* OOSoundSourcePool.h */,
|
||||
1ACBF0700D82DF9B00CC005F /* OOSoundSourcePool.m */,
|
||||
1A047B7C0DCB3D7500EE1CD0 /* OOProbabilitySet.h */,
|
||||
1A047B7D0DCB3D7500EE1CD0 /* OOProbabilitySet.m */,
|
||||
);
|
||||
name = Utilities;
|
||||
sourceTree = "<group>";
|
||||
@ -2592,6 +2608,8 @@
|
||||
children = (
|
||||
1ACEA3470C91507000C7CE97 /* OORoleSet.h */,
|
||||
1ACEA3480C91507000C7CE97 /* OORoleSet.m */,
|
||||
1A0479E70DC9F81000EE1CD0 /* OOShipRegistry.h */,
|
||||
1A0479E80DC9F81000EE1CD0 /* OOShipRegistry.m */,
|
||||
);
|
||||
name = "Ship management";
|
||||
sourceTree = "<group>";
|
||||
@ -2843,6 +2861,9 @@
|
||||
1A1616620D7DCFDC0094AE5B /* OOFilteringEnumerator.h in Headers */,
|
||||
1ACBF0AD0D82F79600CC005F /* OOSoundSourcePool.h in Headers */,
|
||||
1A7BA8830D843485003C6CA3 /* ShipEntityScriptMethods.h in Headers */,
|
||||
1A0479E90DC9F81000EE1CD0 /* OOShipRegistry.h in Headers */,
|
||||
1A047A450DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.h in Headers */,
|
||||
1A047B7E0DCB3D7500EE1CD0 /* OOProbabilitySet.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -3189,6 +3210,9 @@
|
||||
1A1616630D7DCFDC0094AE5B /* OOFilteringEnumerator.m in Sources */,
|
||||
1ACBF0AE0D82F79800CC005F /* OOSoundSourcePool.m in Sources */,
|
||||
1A7BA8840D843485003C6CA3 /* ShipEntityScriptMethods.m in Sources */,
|
||||
1A0479EA0DC9F81000EE1CD0 /* OOShipRegistry.m in Sources */,
|
||||
1A047A460DCA0F4F00EE1CD0 /* NSDictionaryOOExtensions.m in Sources */,
|
||||
1A047B7F0DCB3D7500EE1CD0 /* OOProbabilitySet.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1,47 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>constrictor-mission-thief</key>
|
||||
<dict>
|
||||
<key>random_seed</key>
|
||||
<string>1 3 5 7 11 13</string><!-- fix the name and details, but use the key to keep it secret -->
|
||||
<key>bounty</key>
|
||||
<integer>1000</integer><!-- not actually used, we do the reward in the script -->
|
||||
<key>origin</key>
|
||||
<integer>7</integer><!-- system number seven (Lave in Galaxy 0) -->
|
||||
<key>script_actions</key>
|
||||
<!--
|
||||
check if docked
|
||||
print congratulatory message from the Imperial Navy
|
||||
award a special bounty
|
||||
-->
|
||||
<array>
|
||||
<dict>
|
||||
<key>conditions</key>
|
||||
<array>
|
||||
<string>status_string equal STATUS_DOCKED</string>
|
||||
</array>
|
||||
<key>do</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>conditions</key>
|
||||
<array>
|
||||
<string>gui_screen_string notequal GUI_SCREEN_MISSION</string>
|
||||
</array>
|
||||
<key>do</key>
|
||||
<array>
|
||||
<string>setMissionMusic: none</string>
|
||||
<string>setMissionImage: none</string>
|
||||
<string>showShipModel: none</string>
|
||||
<string>setGuiToMissionScreen</string>
|
||||
</array>
|
||||
</dict>
|
||||
<string>awardCredits: 1000</string>
|
||||
<string>addMissionText: conhunt-thief-captured</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
{
|
||||
"constrictor-mission-thief" =
|
||||
{
|
||||
"random_seed" = "1 3 5 7 11 13"; // fix the name and details, but use the key to keep it secret
|
||||
bounty = 1000; // not actually used, we do the reward in the script
|
||||
origin = 7; // system number seven (Lave in Galaxy 0)
|
||||
"script_actions" =
|
||||
(
|
||||
/*
|
||||
check if docked
|
||||
print congratulatory message from the Imperial Navy
|
||||
award a special bounty
|
||||
*/
|
||||
{
|
||||
conditions =
|
||||
(
|
||||
"status_string equal STATUS_DOCKED"
|
||||
);
|
||||
do =
|
||||
(
|
||||
{
|
||||
conditions =
|
||||
(
|
||||
"gui_screen_string notequal GUI_SCREEN_MISSION"
|
||||
);
|
||||
do = (
|
||||
"setMissionMusic: none",
|
||||
"setMissionImage: none",
|
||||
"showShipModel: none",
|
||||
"setGuiToMissionScreen"
|
||||
);
|
||||
},
|
||||
"awardCredits: 1000",
|
||||
"addMissionText: conhunt-thief-captured"
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@ -1,33 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<array>
|
||||
<string>coriolis-station</string>
|
||||
<string>boa-mk2</string>
|
||||
<string>transporter</string>
|
||||
<string>alloy</string>
|
||||
<string>cobramk1</string>
|
||||
<string>worm</string>
|
||||
<string>viper</string>
|
||||
<string>asteroid</string>
|
||||
<string>barrel</string>
|
||||
<string>python</string>
|
||||
<string>missile</string>
|
||||
<string>tharglet</string>
|
||||
<string>thargoid</string>
|
||||
<string>boa</string>
|
||||
<string>shuttle</string>
|
||||
<string>dodecahedron-station</string>
|
||||
<string>sidewinder</string>
|
||||
<string>moray</string>
|
||||
<string>mamba</string>
|
||||
<string>krait</string>
|
||||
<string>boulder</string>
|
||||
<string>ferdelance</string>
|
||||
<string>gecko</string>
|
||||
<string>anaconda</string>
|
||||
<string>escape-capsule</string>
|
||||
<string>adder</string>
|
||||
<string>asp</string>
|
||||
</array>
|
||||
</plist>
|
||||
(
|
||||
"coriolis-station",
|
||||
"boa-mk2",
|
||||
transporter,
|
||||
alloy,
|
||||
cobramk1,
|
||||
worm,
|
||||
viper,
|
||||
asteroid,
|
||||
barrel,
|
||||
python,
|
||||
missile,
|
||||
tharglet,
|
||||
thargoid,
|
||||
boa,
|
||||
shuttle,
|
||||
"dodecahedron-station",
|
||||
sidewinder,
|
||||
moray,
|
||||
mamba,
|
||||
krait,
|
||||
boulder,
|
||||
ferdelance,
|
||||
gecko,
|
||||
anaconda,
|
||||
"escape-capsule",
|
||||
adder,
|
||||
asp
|
||||
)
|
||||
|
@ -922,6 +922,10 @@ static PlayerEntity *sSharedPlayer = nil;
|
||||
|
||||
- (BOOL) setUpShipFromDictionary:(NSDictionary *)shipDict
|
||||
{
|
||||
// In order for default values to work and float values to not be junk,
|
||||
// replace nil with empty dictionary. -- Ahruman 2008-05-01
|
||||
if (shipDict == nil) shipDict = [NSDictionary dictionary];
|
||||
|
||||
[shipinfoDictionary release];
|
||||
shipinfoDictionary = [shipDict copy];
|
||||
|
||||
|
61
src/Core/NSDictionaryOOExtensions.h
Normal file
61
src/Core/NSDictionaryOOExtensions.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
|
||||
NSDictionaryOOExtensions.h
|
||||
|
||||
Extensions to NSDictionary.
|
||||
|
||||
|
||||
Oolite
|
||||
Copyright (C) 2004-2008 Giles C Williams and contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
|
||||
This file may also be distributed under the MIT/X11 license:
|
||||
|
||||
Copyright (C) 2008 Jens Ayton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#import "OOCocoa.h"
|
||||
|
||||
|
||||
@interface NSDictionary (OOExtensions)
|
||||
|
||||
// These all return self if passed nil paramters. They all return a new immutable dictionary if sent to a mutable dictionary.
|
||||
- (NSDictionary *) dictionaryByAddingObject:(id)object forKey:(id)key;
|
||||
- (NSDictionary *) dictionaryByRemovingObjectForKey:(id)key;
|
||||
- (NSDictionary *) dictionaryByAddingEntriesFromDictionary:(NSDictionary *)dictionary;
|
||||
|
||||
@end
|
95
src/Core/NSDictionaryOOExtensions.m
Normal file
95
src/Core/NSDictionaryOOExtensions.m
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
|
||||
NSDictionaryOOExtensions.m
|
||||
|
||||
|
||||
Oolite
|
||||
Copyright (C) 2004-2008 Giles C Williams and contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
|
||||
This file may also be distributed under the MIT/X11 license:
|
||||
|
||||
Copyright (C) 2008 Jens Ayton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#import "NSDictionaryOOExtensions.h"
|
||||
|
||||
|
||||
@implementation NSDictionary (OOExtensions)
|
||||
|
||||
- (NSDictionary *) dictionaryByAddingObject:(id)object forKey:(id)key
|
||||
{
|
||||
// Note: object lifetime issues aside, we need to copy and autorelease so that the right thing happens for mutable dictionaries.
|
||||
if (object == nil || key == nil) return [[self copy] autorelease];
|
||||
|
||||
NSMutableDictionary *temp = [self mutableCopy];
|
||||
[temp setObject:object forKey:key];
|
||||
NSDictionary *result = [[temp copy] autorelease];
|
||||
[temp release];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) dictionaryByRemovingObjectForKey:(id)key
|
||||
{
|
||||
// Note: object lifetime issues aside, we need to copy and autorelease so that the right thing happens for mutable dictionaries.
|
||||
if (key == nil) return [[self copy] autorelease];
|
||||
|
||||
NSMutableDictionary *temp = [self mutableCopy];
|
||||
[temp removeObjectForKey:key];
|
||||
NSDictionary *result = [[temp copy] autorelease];
|
||||
[temp release];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) dictionaryByAddingEntriesFromDictionary:(NSDictionary *)dictionary
|
||||
{
|
||||
// Note: object lifetime issues aside, we need to copy and autorelease so that the right thing happens for mutable dictionaries.
|
||||
if (dictionary == nil) return [[self copy] autorelease];
|
||||
|
||||
NSMutableDictionary *temp = [self mutableCopy];
|
||||
[temp addEntriesFromDictionary:dictionary];
|
||||
NSDictionary *result = [[temp copy] autorelease];
|
||||
[temp release];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
@ -64,7 +64,7 @@ static NSString * const kCacheKeyCaches = @"_caches";
|
||||
enum
|
||||
{
|
||||
kEndianTagValue = 0x12345678UL,
|
||||
kFormatVersionValue = 14
|
||||
kFormatVersionValue = 15
|
||||
};
|
||||
|
||||
|
||||
|
@ -265,11 +265,11 @@ enum
|
||||
@implementation OOMusicController (Singleton)
|
||||
|
||||
/* Canonical singleton boilerplate.
|
||||
See Cocoa Fundamentals Guide: Creating a Singleton Instance.
|
||||
See also +sharedController above.
|
||||
See Cocoa Fundamentals Guide: Creating a Singleton Instance.
|
||||
See also +sharedController above.
|
||||
|
||||
NOTE: assumes single-threaded access.
|
||||
*/
|
||||
NOTE: assumes single-threaded access.
|
||||
*/
|
||||
|
||||
+ (id) allocWithZone:(NSZone *)inZone
|
||||
{
|
||||
|
99
src/Core/OOProbabilitySet.h
Normal file
99
src/Core/OOProbabilitySet.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
|
||||
OOProbabilitySet.h
|
||||
|
||||
A collection for selecting objects randomly, with probability weighting.
|
||||
Probability weights can be 0 - an object may be in the set but not selectable.
|
||||
Comes in mutable and immutable variants.
|
||||
|
||||
Performance characteristics:
|
||||
* -randomObject, the primary method, is O(log n) for immutable
|
||||
OOProbabilitySets and O(n) for mutable ones.
|
||||
* -containsObject: and -probabilityForObject: are O(n). This could be
|
||||
optimized, but there's currently no need.
|
||||
|
||||
|
||||
Oolite
|
||||
Copyright (C) 2004-2008 Giles C Williams and contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
|
||||
This file may also be distributed under the MIT/X11 license:
|
||||
|
||||
Copyright (C) 2008 Jens Ayton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#import "OOCocoa.h"
|
||||
|
||||
|
||||
@interface OOProbabilitySet: NSObject <NSCopying, NSMutableCopying>
|
||||
|
||||
+ (id) probabilitySet;
|
||||
+ (id) probabilitySetWithObjects:(id *)objects weights:(float *)weights count:(unsigned long)count;
|
||||
+ (id) probabilitySetWithPropertyListRepresentation:(NSDictionary *)plist;
|
||||
|
||||
- (id) init;
|
||||
- (id) initWithObjects:(id *)objects weights:(float *)weights count:(unsigned)count;
|
||||
- (id) initWithPropertyListRepresentation:(NSDictionary *)plist;
|
||||
|
||||
// propertyListRepresentation is only valid if objects are property list objects.
|
||||
- (NSDictionary *) propertyListRepresentation;
|
||||
|
||||
- (unsigned long) count;
|
||||
- (id) randomObject;
|
||||
|
||||
- (float) weightForObject:(id)object; // Returns -1 for unknown objects.
|
||||
- (float) sumOfWeights;
|
||||
- (NSArray *) allObjects;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OOProbabilitySet (OOExtendedProbabilitySet)
|
||||
|
||||
- (BOOL) containsObject:(id)object;
|
||||
- (NSEnumerator *) objectEnumerator;
|
||||
- (float) probabilityForObject:(id)object; // Returns -1 for unknown objects, or a value from 0 to 1 inclusive for known objects.
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OOMutableProbabilitySet: OOProbabilitySet
|
||||
|
||||
- (void) setWeight:(float)weight forObject:(id)object; // Adds object if needed.
|
||||
- (void) removeObject:(id)object;
|
||||
|
||||
@end
|
977
src/Core/OOProbabilitySet.m
Normal file
977
src/Core/OOProbabilitySet.m
Normal file
@ -0,0 +1,977 @@
|
||||
/*
|
||||
|
||||
OOProbabilitySet.m
|
||||
|
||||
|
||||
Oolite
|
||||
Copyright (C) 2004-2008 Giles C Williams and contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
|
||||
This file may also be distributed under the MIT/X11 license:
|
||||
|
||||
Copyright (C) 2008 Jens Ayton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
IMPLEMENTATION NOTES
|
||||
OOProbabilitySet is implemented as a class cluster with two abstract classes,
|
||||
two special-case implementations for immutable sets with zero or one object,
|
||||
and two general implementations (one mutable and one immutable). The general
|
||||
implementations are the only non-trivial ones.
|
||||
|
||||
The general immutable implementation, OOConcreteProbabilitySet, consists of
|
||||
two parallel arrays, one of objects and one of cumulative weights. The
|
||||
"cumulative weight" for an entry is the sum of its weight and the cumulative
|
||||
weight of the entry to the left (i.e., with a lower index), with the implicit
|
||||
entry -1 having a cumulative weight of 0. Since weight cannot be negative,
|
||||
this means that cumulative weights increase to the right (not strictly
|
||||
increasing, though, since weights may be zero). We can thus find an object
|
||||
with a given cumulative weight through a binary search.
|
||||
|
||||
OOConcreteMutableProbabilitySet is a naïve implementation using arrays. It
|
||||
could be optimized, but isn't expected to be used much except for building
|
||||
sets that will then be immutablized.
|
||||
|
||||
*/
|
||||
|
||||
#import "OOProbabilitySet.h"
|
||||
#import "OOFunctionAttributes.h"
|
||||
#import "OOCollectionExtractors.h"
|
||||
#import "legacy_random.h"
|
||||
|
||||
|
||||
static NSString * const kObjectsKey = @"objects";
|
||||
static NSString * const kWeightsKey = @"weights";
|
||||
|
||||
|
||||
@protocol OOProbabilitySetEnumerable <NSObject>
|
||||
|
||||
- (id) privObjectAtIndex:(unsigned long)index;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OOProbabilitySet (OOPrivate)
|
||||
|
||||
// Designated initializer. This must be used by subclasses, since init is overriden for public use.
|
||||
- (id) initPriv;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OOEmptyProbabilitySet: OOProbabilitySet
|
||||
|
||||
+ (OOEmptyProbabilitySet *) singleton;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OOSingleObjectProbabilitySet: OOProbabilitySet
|
||||
{
|
||||
id _object;
|
||||
float _weight;
|
||||
}
|
||||
|
||||
- (id) initWithObject:(id)object weight:(float)weight;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OOConcreteProbabilitySet: OOProbabilitySet <OOProbabilitySetEnumerable>
|
||||
{
|
||||
unsigned long _count;
|
||||
id *_objects;
|
||||
float *_cumulativeWeights; // Each cumulative weight is weight of object at this index + weight of all objects to left.
|
||||
float _sumOfWeights;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@interface OOConcreteMutableProbabilitySet: OOMutableProbabilitySet
|
||||
{
|
||||
NSMutableArray *_objects;
|
||||
NSMutableArray *_weights;
|
||||
float _sumOfWeights;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@interface OOProbabilitySetEnumerator: NSEnumerator
|
||||
{
|
||||
id _enumerable;
|
||||
unsigned long _index;
|
||||
}
|
||||
|
||||
- (id) initWithEnumerable:(id<OOProbabilitySetEnumerable>)enumerable;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static void ThrowAbstractionViolationException(id obj) GCC_ATTR((noreturn));
|
||||
|
||||
|
||||
@implementation OOProbabilitySet
|
||||
|
||||
// Abstract class just tosses allocations over to concrete class, and throws exception if you try to use it directly.
|
||||
|
||||
+ (id) probabilitySet
|
||||
{
|
||||
return [OOEmptyProbabilitySet singleton];
|
||||
}
|
||||
|
||||
|
||||
+ (id) probabilitySetWithObjects:(id *)objects weights:(float *)weights count:(unsigned long)count
|
||||
{
|
||||
return [[[self alloc] initWithObjects:objects weights:weights count:count] autorelease];
|
||||
}
|
||||
|
||||
|
||||
+ (id) probabilitySetWithPropertyListRepresentation:(NSDictionary *)plist
|
||||
{
|
||||
return [[[self alloc] initWithPropertyListRepresentation:plist] autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (id) init
|
||||
{
|
||||
[self release];
|
||||
return [OOEmptyProbabilitySet singleton];
|
||||
}
|
||||
|
||||
|
||||
- (id) initWithObjects:(id *)objects weights:(float *)weights count:(unsigned)count
|
||||
{
|
||||
NSZone *zone = [self zone];
|
||||
[self release];
|
||||
self = nil;
|
||||
|
||||
// Zero objects: return empty-set singleton.
|
||||
if (count == 0) return [OOEmptyProbabilitySet singleton];
|
||||
|
||||
// If count is not zero and one of the paramters is nil, we've got us a programming error.
|
||||
if (objects == NULL || weights == NULL)
|
||||
{
|
||||
[NSException raise:NSInvalidArgumentException format:@"Attempt to create %@ with non-zero count but nil objects or weights.", @"OOProbabilitySet"];
|
||||
}
|
||||
|
||||
// Single object: simple one-object set. Expected to be quite common.
|
||||
if (count == 1) return [[OOSingleObjectProbabilitySet allocWithZone:zone] initWithObject:objects[0] weight:weights[0]];
|
||||
|
||||
// Otherwise, use general implementation.
|
||||
return [[OOConcreteProbabilitySet allocWithZone:zone] initWithObjects:objects weights:weights count:count];
|
||||
}
|
||||
|
||||
|
||||
- (id) initWithPropertyListRepresentation:(NSDictionary *)plist
|
||||
{
|
||||
NSArray *objects = nil;
|
||||
NSArray *weights = nil;
|
||||
unsigned long i = 0, count = 0;
|
||||
id *rawObjects = NULL;
|
||||
float *rawWeights = NULL;
|
||||
|
||||
objects = [plist arrayForKey:kObjectsKey];
|
||||
weights = [plist arrayForKey:kWeightsKey];
|
||||
|
||||
// Validate
|
||||
if (objects == nil || weights == nil) return nil;
|
||||
count = [objects count];
|
||||
if (count != [weights count]) return nil;
|
||||
|
||||
// Extract contents.
|
||||
rawObjects = malloc(sizeof *rawObjects * count);
|
||||
rawWeights = malloc(sizeof *rawWeights * count);
|
||||
|
||||
if (rawObjects != NULL || rawWeights != NULL)
|
||||
{
|
||||
// Extract objects.
|
||||
[objects getObjects:rawObjects];
|
||||
|
||||
// Extract and convert weights.
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
rawWeights[i] = fmaxf([weights floatAtIndex:i], 0.0f);
|
||||
}
|
||||
|
||||
self = [self initWithObjects:rawObjects weights:rawWeights count:count];
|
||||
}
|
||||
else
|
||||
{
|
||||
self = nil;
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
free(rawObjects);
|
||||
free(rawWeights);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id) initPriv
|
||||
{
|
||||
return [super init];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *) descriptionComponents
|
||||
{
|
||||
return [NSString stringWithFormat:@"count=%lu", [self count]];
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) propertyListRepresentation
|
||||
{
|
||||
ThrowAbstractionViolationException(self);
|
||||
}
|
||||
|
||||
- (id) randomObject
|
||||
{
|
||||
ThrowAbstractionViolationException(self);
|
||||
}
|
||||
|
||||
|
||||
- (float) weightForObject:(id)object
|
||||
{
|
||||
ThrowAbstractionViolationException(self);
|
||||
}
|
||||
|
||||
|
||||
- (float) sumOfWeights
|
||||
{
|
||||
ThrowAbstractionViolationException(self);
|
||||
}
|
||||
|
||||
|
||||
- (unsigned long) count
|
||||
{
|
||||
ThrowAbstractionViolationException(self);
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) allObjects
|
||||
{
|
||||
ThrowAbstractionViolationException(self);
|
||||
}
|
||||
|
||||
|
||||
- (id) copyWithZone:(NSZone *)zone
|
||||
{
|
||||
if (zone == [self zone])
|
||||
{
|
||||
return [self retain];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [[OOProbabilitySet allocWithZone:zone] initWithPropertyListRepresentation:[self propertyListRepresentation]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (id) mutableCopyWithZone:(NSZone *)zone
|
||||
{
|
||||
return [[OOMutableProbabilitySet allocWithZone:zone] initWithPropertyListRepresentation:[self propertyListRepresentation]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOProbabilitySet (OOExtendedProbabilitySet)
|
||||
|
||||
- (BOOL) containsObject:(id)object
|
||||
{
|
||||
return [self weightForObject:object] >= 0.0f;
|
||||
}
|
||||
|
||||
|
||||
- (NSEnumerator *) objectEnumerator
|
||||
{
|
||||
return [[self allObjects] objectEnumerator];
|
||||
}
|
||||
|
||||
|
||||
- (float) probabilityForObject:(id)object
|
||||
{
|
||||
float weight = [self weightForObject:object];
|
||||
if (weight > 0) weight /= [self sumOfWeights];
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static OOEmptyProbabilitySet *sOOEmptyProbabilitySetSingleton = nil;
|
||||
|
||||
@implementation OOEmptyProbabilitySet: OOProbabilitySet
|
||||
|
||||
+ (OOEmptyProbabilitySet *) singleton
|
||||
{
|
||||
if (sOOEmptyProbabilitySetSingleton == nil)
|
||||
{
|
||||
[[self alloc] init];
|
||||
}
|
||||
|
||||
return sOOEmptyProbabilitySetSingleton;
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) propertyListRepresentation
|
||||
{
|
||||
NSArray *empty = [NSArray array];
|
||||
return [NSDictionary dictionaryWithObjectsAndKeys:empty, kObjectsKey, empty, kWeightsKey, nil];
|
||||
}
|
||||
|
||||
|
||||
- (id) randomObject
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (float) weightForObject:(id)object
|
||||
{
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
|
||||
- (float) sumOfWeights
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
- (unsigned long) count
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) allObjects
|
||||
{
|
||||
return [NSArray array];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOEmptyProbabilitySet (Singleton)
|
||||
|
||||
/* Canonical singleton boilerplate.
|
||||
See Cocoa Fundamentals Guide: Creating a Singleton Instance.
|
||||
See also +singleton above.
|
||||
|
||||
NOTE: assumes single-threaded access.
|
||||
*/
|
||||
|
||||
+ (id) allocWithZone:(NSZone *)inZone
|
||||
{
|
||||
if (sOOEmptyProbabilitySetSingleton == nil)
|
||||
{
|
||||
sOOEmptyProbabilitySetSingleton = [super allocWithZone:inZone];
|
||||
return sOOEmptyProbabilitySetSingleton;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (id) copyWithZone:(NSZone *)inZone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id) retain
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (unsigned) retainCount
|
||||
{
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
|
||||
- (void) release
|
||||
{}
|
||||
|
||||
|
||||
- (id) autorelease
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOSingleObjectProbabilitySet: OOProbabilitySet
|
||||
|
||||
- (id) initWithObject:(id)object weight:(float)weight
|
||||
{
|
||||
if (object == nil)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ((self = [super initPriv]))
|
||||
{
|
||||
_object = [object retain];
|
||||
_weight = fmaxf(weight, 0.0f);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_object release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) propertyListRepresentation
|
||||
{
|
||||
return [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSArray arrayWithObject:_object], kObjectsKey,
|
||||
[NSArray arrayWithObject:[NSNumber numberWithFloat:_weight]], kWeightsKey,
|
||||
nil];
|
||||
}
|
||||
|
||||
|
||||
- (id) randomObject
|
||||
{
|
||||
return _object;
|
||||
}
|
||||
|
||||
|
||||
- (float) weightForObject:(id)object
|
||||
{
|
||||
if ([_object isEqual:object]) return _weight;
|
||||
else return -1.0f;
|
||||
}
|
||||
|
||||
|
||||
- (float) sumOfWeights
|
||||
{
|
||||
return _weight;
|
||||
}
|
||||
|
||||
|
||||
- (unsigned long) count
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) allObjects
|
||||
{
|
||||
return [NSArray arrayWithObject:_object];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOConcreteProbabilitySet
|
||||
|
||||
- (id) initWithObjects:(id *)objects weights:(float *)weights count:(unsigned)count
|
||||
{
|
||||
unsigned long i = 0;
|
||||
float cuWeight = 0.0f;
|
||||
|
||||
assert(count > 1 && objects != NULL && weights != NULL);
|
||||
|
||||
if ((self = [super initPriv]))
|
||||
{
|
||||
// Allocate arrays
|
||||
_objects = malloc(sizeof *objects * count);
|
||||
_cumulativeWeights = malloc(sizeof *_cumulativeWeights * count);
|
||||
if (_objects == NULL || _cumulativeWeights == NULL)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Fill in arrays, retain objects, add up weights.
|
||||
for (i = 0; i != count; ++i)
|
||||
{
|
||||
_objects[i] = [objects[i] retain];
|
||||
cuWeight += weights[i];
|
||||
_cumulativeWeights[i] = cuWeight;
|
||||
}
|
||||
_count = count;
|
||||
_sumOfWeights = cuWeight;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
unsigned long i = 0;
|
||||
|
||||
if (_objects != NULL)
|
||||
{
|
||||
for (i = 0; i < _count; ++i)
|
||||
{
|
||||
[_objects[i] release];
|
||||
}
|
||||
free(_objects);
|
||||
_objects = NULL;
|
||||
}
|
||||
|
||||
if (_cumulativeWeights != NULL)
|
||||
{
|
||||
free(_cumulativeWeights);
|
||||
_cumulativeWeights = NULL;
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) propertyListRepresentation
|
||||
{
|
||||
NSArray *objects = nil;
|
||||
NSMutableArray *weights = nil;
|
||||
float cuWeight = 0.0f, sum = 0.0f;
|
||||
unsigned long i = 0;
|
||||
|
||||
objects = [NSArray arrayWithObjects:_objects count:_count];
|
||||
weights = [NSMutableArray arrayWithCapacity:_count];
|
||||
for (i = 0; i < _count; ++i)
|
||||
{
|
||||
cuWeight = _cumulativeWeights[i];
|
||||
[weights addFloat:cuWeight - sum];
|
||||
sum = cuWeight;
|
||||
}
|
||||
|
||||
return [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
objects, kObjectsKey,
|
||||
[[weights copy] autorelease], kWeightsKey,
|
||||
nil];
|
||||
}
|
||||
|
||||
- (unsigned long) count
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
|
||||
- (id) privObjectForWeight:(float)target
|
||||
{
|
||||
/* Select an object at random. This is a binary search in the cumulative
|
||||
weights array. Since weights of zero are allowed, there may be several
|
||||
objects with the same cumulative weight, in which case we select the
|
||||
leftmost, i.e. the one where the delta is non-zero.
|
||||
*/
|
||||
|
||||
unsigned long low = 0, high = _count - 1, idx = 0;
|
||||
float weight;
|
||||
|
||||
while (low < high)
|
||||
{
|
||||
idx = (low + high) / 2;
|
||||
weight = _cumulativeWeights[idx];
|
||||
if (weight > target)
|
||||
{
|
||||
if (EXPECT_NOT(idx == 0)) break;
|
||||
high = idx - 1;
|
||||
}
|
||||
else if (weight < target) low = idx + 1;
|
||||
else break;
|
||||
}
|
||||
|
||||
if (weight > target)
|
||||
{
|
||||
while (idx > 0 && _cumulativeWeights[idx - 1] >= target) --idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (idx < (_count - 1) && _cumulativeWeights[idx] < target) ++idx;
|
||||
}
|
||||
|
||||
assert(idx < _count);
|
||||
id result = _objects[idx];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (id) randomObject
|
||||
{
|
||||
if (_sumOfWeights <= 0.0f) return nil;
|
||||
return [self privObjectForWeight:randf() * _sumOfWeights];
|
||||
}
|
||||
|
||||
|
||||
- (float) weightForObject:(id)object
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
// Can't have nil in collection.
|
||||
if (object == nil) return -1.0f;
|
||||
|
||||
// Perform linear search, then get weight by subtracting cumulative weight from cumulative weight to left.
|
||||
for (i = 0; i < _count; ++i)
|
||||
{
|
||||
if ([_objects[i] isEqual:object])
|
||||
{
|
||||
float leftWeight = (i != 0) ? _cumulativeWeights[i - 1] : 0.0f;
|
||||
return _cumulativeWeights[i] - leftWeight;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, object not found.
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
|
||||
- (float) sumOfWeights
|
||||
{
|
||||
return _sumOfWeights;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) allObjects
|
||||
{
|
||||
return [NSArray arrayWithObjects:_objects count:_count];
|
||||
}
|
||||
|
||||
|
||||
- (NSEnumerator *) objectEnumerator
|
||||
{
|
||||
return [[[OOProbabilitySetEnumerator alloc] initWithEnumerable:self] autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (id) privObjectAtIndex:(unsigned long)index
|
||||
{
|
||||
return (index < _count) ? _objects[index] : nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOMutableProbabilitySet
|
||||
|
||||
+ (id) probabilitySet
|
||||
{
|
||||
return [[[OOConcreteMutableProbabilitySet alloc] initPriv] autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (id) init
|
||||
{
|
||||
NSZone *zone = [self zone];
|
||||
[self release];
|
||||
return [[OOConcreteMutableProbabilitySet allocWithZone:zone] initPriv];
|
||||
}
|
||||
|
||||
|
||||
- (id) initWithObjects:(id *)objects weights:(float *)weights count:(unsigned)count
|
||||
{
|
||||
NSZone *zone = [self zone];
|
||||
[self release];
|
||||
return [[OOConcreteMutableProbabilitySet allocWithZone:zone] initWithObjects:objects weights:weights count:count];
|
||||
}
|
||||
|
||||
|
||||
- (id) initWithPropertyListRepresentation:(NSDictionary *)plist
|
||||
{
|
||||
NSZone *zone = [self zone];
|
||||
[self release];
|
||||
return [[OOConcreteMutableProbabilitySet allocWithZone:zone] initWithPropertyListRepresentation:plist];
|
||||
}
|
||||
|
||||
|
||||
- (id) copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return [[OOProbabilitySet allocWithZone:zone] initWithPropertyListRepresentation:[self propertyListRepresentation]];
|
||||
}
|
||||
|
||||
|
||||
- (void) setWeight:(float)weight forObject:(id)object
|
||||
{
|
||||
ThrowAbstractionViolationException(self);
|
||||
}
|
||||
|
||||
|
||||
- (void) removeObject:(id)object
|
||||
{
|
||||
ThrowAbstractionViolationException(self);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOConcreteMutableProbabilitySet
|
||||
|
||||
- (id) initPriv
|
||||
{
|
||||
if ((self = [super initPriv]))
|
||||
{
|
||||
_objects = [[NSMutableArray alloc] init];
|
||||
_weights = [[NSMutableArray alloc] init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id) initWithObjects:(id *)objects weights:(float *)weights count:(unsigned)count
|
||||
{
|
||||
unsigned long i = 0;
|
||||
|
||||
// Validate parameters.
|
||||
if (count != 0 && (objects == NULL || weights == NULL))
|
||||
{
|
||||
[self release];
|
||||
[NSException raise:NSInvalidArgumentException format:@"Attempt to create %@ with non-zero count but nil objects or weights.", @"OOMutableProbabilitySet"];
|
||||
}
|
||||
|
||||
// Set up & go.
|
||||
if ((self == [self initPriv]))
|
||||
{
|
||||
for (i = 0; i != count; ++i)
|
||||
{
|
||||
[self setWeight:fmaxf(weights[i], 0.0f) forObject:objects[i]];
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id) initWithPropertyListRepresentation:(NSDictionary *)plist
|
||||
{
|
||||
BOOL OK = YES;
|
||||
NSArray *objects = nil;
|
||||
NSArray *weights = nil;
|
||||
unsigned long i = 0, count = 0;
|
||||
|
||||
if (!(self = [super initPriv])) OK = NO;
|
||||
|
||||
if (OK)
|
||||
{
|
||||
objects = [plist arrayForKey:kObjectsKey];
|
||||
weights = [plist arrayForKey:kWeightsKey];
|
||||
|
||||
// Validate
|
||||
if (objects == nil || weights == nil) OK = NO;
|
||||
count = [objects count];
|
||||
if (count != [weights count]) OK = NO;
|
||||
}
|
||||
|
||||
if (OK)
|
||||
{
|
||||
for (i = 0; i <= count; ++i)
|
||||
{
|
||||
[self setWeight:[weights floatAtIndex:i] forObject:[objects objectAtIndex:i]];
|
||||
}
|
||||
}
|
||||
|
||||
if (!OK)
|
||||
{
|
||||
[self release];
|
||||
self = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_objects release];
|
||||
[_weights release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) propertyListRepresentation
|
||||
{
|
||||
return [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
_objects, kObjectsKey,
|
||||
_weights, kWeightsKey,
|
||||
nil];
|
||||
}
|
||||
|
||||
|
||||
- (unsigned long) count
|
||||
{
|
||||
return [_objects count];
|
||||
}
|
||||
|
||||
|
||||
- (id) randomObject
|
||||
{
|
||||
float target = 0.0f, sum = 0.0f;
|
||||
unsigned i = 0, count = 0;
|
||||
|
||||
target = randf() * _sumOfWeights;
|
||||
count = [_objects count];
|
||||
if (count == 0 || _sumOfWeights <= 0.0f) return nil;
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
sum += [_weights floatAtIndex:i];
|
||||
if (sum >= target) return [_objects objectAtIndex:i];
|
||||
}
|
||||
|
||||
OOLog(@"probabilitySet.broken", @"%s fell off end, returning first object. Sum = %f, target = %f, count = %u. This is an internal error, please report it.", __PRETTY_FUNCTION__, _sumOfWeights, target, count);
|
||||
return [_objects objectAtIndex:0];
|
||||
}
|
||||
|
||||
|
||||
- (float) weightForObject:(id)object
|
||||
{
|
||||
float result = -1.0f;
|
||||
|
||||
if (object != nil)
|
||||
{
|
||||
unsigned long index = [_objects indexOfObject:object];
|
||||
if (index != NSNotFound)
|
||||
{
|
||||
result = [_weights floatAtIndex:index];
|
||||
if (index != 0) result -= [_weights floatAtIndex:index - 1];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (float) sumOfWeights
|
||||
{
|
||||
return _sumOfWeights;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) allObjects
|
||||
{
|
||||
return [[_objects copy] autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (NSEnumerator *) objectEnumerator
|
||||
{
|
||||
return [_objects objectEnumerator];
|
||||
}
|
||||
|
||||
|
||||
- (void) setWeight:(float)weight forObject:(id)object
|
||||
{
|
||||
if (object == nil) return;
|
||||
|
||||
weight = fmaxf(weight, 0.0f);
|
||||
unsigned long index = [_objects indexOfObject:object];
|
||||
if (index == NSNotFound)
|
||||
{
|
||||
[_objects addObject:object];
|
||||
[_weights addFloat:weight];
|
||||
_sumOfWeights += weight;
|
||||
}
|
||||
else
|
||||
{
|
||||
_sumOfWeights -= [_weights floatAtIndex:index];
|
||||
_sumOfWeights += weight;
|
||||
[_weights replaceObjectAtIndex:index withObject:[NSNumber numberWithFloat:weight]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) removeObject:(id)object
|
||||
{
|
||||
if (object != nil) return;
|
||||
|
||||
unsigned long index = [_objects indexOfObject:object];
|
||||
if (index != NSNotFound)
|
||||
{
|
||||
[_objects removeObjectAtIndex:index];
|
||||
_sumOfWeights -= [_weights floatAtIndex:index];
|
||||
[_weights removeObjectAtIndex:index];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOProbabilitySetEnumerator
|
||||
|
||||
- (id) initWithEnumerable:(id<OOProbabilitySetEnumerable>)enumerable
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_enumerable = [enumerable retain];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_enumerable release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (id) nextObject
|
||||
{
|
||||
if (_index < [_enumerable count])
|
||||
{
|
||||
return [_enumerable privObjectAtIndex:_index++];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_enumerable release];
|
||||
_enumerable = nil;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static void ThrowAbstractionViolationException(id obj)
|
||||
{
|
||||
[NSException raise:NSGenericException format:@"Attempt to use abstract class %@ - this indicates an incorrect initialization.", [obj class]];
|
||||
abort(); // unreachable
|
||||
}
|
@ -86,3 +86,7 @@ SOFTWARE.
|
||||
- (id)roleSetWithRemovedRole:(NSString *)role;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// Returns a dictionary whose keys are roles and whose values are weights.
|
||||
NSDictionary *OOParseRolesFromString(NSString *string);
|
||||
|
@ -56,7 +56,6 @@ SOFTWARE.
|
||||
@interface OORoleSet (OOPrivate)
|
||||
|
||||
- (id)initWithRolesAndProbabilities:(NSDictionary *)dict;
|
||||
- (NSDictionary *)parseRolesFromString:(NSString *)string;
|
||||
|
||||
@end
|
||||
|
||||
@ -78,7 +77,7 @@ SOFTWARE.
|
||||
{
|
||||
NSDictionary *dict = nil;
|
||||
|
||||
dict = [self parseRolesFromString:roleString];
|
||||
dict = OOParseRolesFromString(roleString);
|
||||
return [self initWithRolesAndProbabilities:dict];
|
||||
}
|
||||
|
||||
@ -314,8 +313,10 @@ SOFTWARE.
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
- (NSDictionary *)parseRolesFromString:(NSString *)string
|
||||
|
||||
NSDictionary *OOParseRolesFromString(NSString *string)
|
||||
{
|
||||
NSMutableDictionary *result = nil;
|
||||
NSArray *tokens = nil;
|
||||
@ -359,5 +360,3 @@ SOFTWARE.
|
||||
if ([result count] == 0) result = nil;
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
|
71
src/Core/OOShipRegistry.h
Normal file
71
src/Core/OOShipRegistry.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
|
||||
OOShipRegistry.h
|
||||
|
||||
Manage the set of installed ships.
|
||||
|
||||
|
||||
Oolite
|
||||
Copyright (C) 2004-2008 Giles C Williams and contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
|
||||
This file may also be distributed under the MIT/X11 license:
|
||||
|
||||
Copyright (C) 2008 Jens Ayton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#import "OOCocoa.h"
|
||||
|
||||
|
||||
@interface OOShipRegistry: NSObject
|
||||
{
|
||||
NSDictionary *_shipData;
|
||||
NSArray *_demoShips;
|
||||
NSSet *_playerShips;
|
||||
NSDictionary *_probabilitySets;
|
||||
}
|
||||
|
||||
+ (OOShipRegistry *) sharedRegistry;
|
||||
|
||||
- (NSDictionary *) shipInfoForKey:(NSString *)key;
|
||||
- (NSArray *) shipKeysWithRole:(NSString *)role;
|
||||
- (NSString *) randomShipKeyForRole:(NSString *)role;
|
||||
|
||||
- (NSArray *) demoShipKeys;
|
||||
- (NSSet *) playerShipKeys;
|
||||
|
||||
@end
|
625
src/Core/OOShipRegistry.m
Normal file
625
src/Core/OOShipRegistry.m
Normal file
@ -0,0 +1,625 @@
|
||||
/*
|
||||
|
||||
OOShipRegistry.m
|
||||
|
||||
|
||||
Oolite
|
||||
Copyright (C) 2004-2008 Giles C Williams and contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
|
||||
This file may also be distributed under the MIT/X11 license:
|
||||
|
||||
Copyright (C) 2008 Jens Ayton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#import "OOShipRegistry.h"
|
||||
#import "OOCacheManager.h"
|
||||
#import "ResourceManager.h"
|
||||
#import "OOCollectionExtractors.h"
|
||||
#import "NSDictionaryOOExtensions.h"
|
||||
#import "OOProbabilitySet.h"
|
||||
#import "OORoleSet.h"
|
||||
|
||||
|
||||
static OOShipRegistry *sSingleton = nil;
|
||||
|
||||
static NSString * const kShipRegistryCacheName = @"ship registry";
|
||||
static NSString * const kShipDataCacheKey = @"ship data";
|
||||
static NSString * const kPlayerShipsCacheKey = @"player ships";
|
||||
static NSString * const kDemoShipsCacheKey = @"demo ships";
|
||||
static NSString * const kRoleWeightsCacheKey = @"role weights";
|
||||
static NSString * const kDefaultDemoShip = @"coriolis-station";
|
||||
|
||||
|
||||
@interface OOShipRegistry (Loader)
|
||||
|
||||
- (void) loadShipData;
|
||||
- (void) loadDemoShips;
|
||||
- (void) loadCachedRoleProbabilitySets;
|
||||
- (void) buildRoleProbabilitySets;
|
||||
|
||||
- (BOOL) applyLikeShips:(NSMutableDictionary *)ioData;
|
||||
- (NSDictionary *) mergeShip:(NSDictionary *)child withParent:(NSDictionary *)parent;
|
||||
- (BOOL) loadAndMergeShipyard:(NSMutableDictionary *)ioData;
|
||||
- (BOOL) loadAndApplyShipDataOverrides:(NSMutableDictionary *)ioData;
|
||||
- (BOOL) isValidShipEntry:(NSDictionary *)shipEntry name:(NSString *)name;
|
||||
- (void) mergeShipRoles:(NSString *)roles forShipKey:(NSString *)shipKey intoProbabilityMap:(NSMutableDictionary *)probabilitySets;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOShipRegistry
|
||||
|
||||
+ (OOShipRegistry *) sharedRegistry
|
||||
{
|
||||
if (sSingleton == nil)
|
||||
{
|
||||
[[self alloc] init];
|
||||
}
|
||||
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
OOCacheManager *cache = [OOCacheManager sharedCache];
|
||||
|
||||
_shipData = [[cache objectForKey:kShipDataCacheKey inCache:kShipRegistryCacheName] retain];
|
||||
_playerShips = [[NSSet setWithArray:[cache objectForKey:kPlayerShipsCacheKey inCache:kShipRegistryCacheName]] retain];
|
||||
if ([_shipData count] == 0) // Don't accept nil or empty
|
||||
{
|
||||
[self loadShipData];
|
||||
if ([_shipData count] == 0)
|
||||
{
|
||||
[NSException raise:@"OOShipRegistryLoadFailure" format:@"Could not load any ship data."];
|
||||
}
|
||||
if ([_playerShips count] == 0)
|
||||
{
|
||||
[NSException raise:@"OOShipRegistryLoadFailure" format:@"Could not load any player ships."];
|
||||
}
|
||||
}
|
||||
|
||||
_demoShips = [[cache objectForKey:kDemoShipsCacheKey inCache:kShipRegistryCacheName] retain];
|
||||
if ([_demoShips count] == 0)
|
||||
{
|
||||
[self loadDemoShips];
|
||||
if ([_demoShips count] == 0)
|
||||
{
|
||||
[NSException raise:@"OOShipRegistryLoadFailure" format:@"Could not load or synthesize any demo ships."];
|
||||
}
|
||||
}
|
||||
|
||||
[self loadCachedRoleProbabilitySets];
|
||||
if (_probabilitySets == nil)
|
||||
{
|
||||
[self buildRoleProbabilitySets];
|
||||
if ([_probabilitySets count] == 0)
|
||||
{
|
||||
[NSException raise:@"OOShipRegistryLoadFailure" format:@"Could not load or synthesize role probability sets."];
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_shipData release];
|
||||
[_demoShips release];
|
||||
[_playerShips release];
|
||||
[_probabilitySets release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) shipInfoForKey:(NSString *)key
|
||||
{
|
||||
return [_shipData objectForKey:key];
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) shipKeysWithRole:(NSString *)role
|
||||
{
|
||||
if (role == nil) return nil;
|
||||
return [[_probabilitySets objectForKey:role] allObjects];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *) randomShipKeyForRole:(NSString *)role
|
||||
{
|
||||
if (role == nil) return nil;
|
||||
return [[_probabilitySets objectForKey:role] randomObject];
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) demoShipKeys
|
||||
{
|
||||
return _demoShips;
|
||||
}
|
||||
|
||||
|
||||
- (NSSet *) playerShipKeys
|
||||
{
|
||||
return _playerShips;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOShipRegistry (Loader)
|
||||
|
||||
/* -loadShipData
|
||||
|
||||
Load the data for all ships. This consists of five stages:
|
||||
* Load merges shipdata.plist dictionary.
|
||||
* Apply all like_ship entries.
|
||||
* Load shipdata-overrides.plist and apply patches.
|
||||
* Load shipyard.plist, add shipyard data into ship dictionaries, and
|
||||
create _playerShips array.
|
||||
* Build role->ship type probability sets.
|
||||
*/
|
||||
- (void) loadShipData
|
||||
{
|
||||
NSMutableDictionary *result = nil;
|
||||
NSEnumerator *enumerator = nil;
|
||||
NSString *key = nil;
|
||||
NSDictionary *immutableResult = nil;
|
||||
|
||||
[_shipData release];
|
||||
_shipData = nil;
|
||||
[_playerShips release];
|
||||
_playerShips = nil;
|
||||
|
||||
// Load shipdata.plist.
|
||||
result = [[[ResourceManager dictionaryFromFilesNamed:@"shipdata.plist"
|
||||
inFolder:@"Config"
|
||||
mergeMode:MERGE_BASIC
|
||||
cache:NO] mutableCopy] autorelease];
|
||||
if (result == nil) return;
|
||||
|
||||
// Clean out any non-dictionaries.
|
||||
for (enumerator = [result keyEnumerator]; (key = [enumerator nextObject]); )
|
||||
{
|
||||
if (![self isValidShipEntry:[result objectForKey:key] name:key])
|
||||
{
|
||||
[result removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve like_ship entries.
|
||||
if (![self applyLikeShips:result]) return;
|
||||
|
||||
// Apply patches.
|
||||
if (![self loadAndApplyShipDataOverrides:result]) return;
|
||||
|
||||
// Add shipyard entries into shipdata entries.
|
||||
if (![self loadAndMergeShipyard:result]) return;
|
||||
|
||||
immutableResult = [[result copy] autorelease];
|
||||
|
||||
_shipData = [immutableResult retain];
|
||||
[[OOCacheManager sharedCache] setObject:_shipData forKey:kShipDataCacheKey inCache:kShipRegistryCacheName];
|
||||
}
|
||||
|
||||
|
||||
/* -loadDemoShips
|
||||
|
||||
Load demoships.plist, and filter out non-existent ships. If no existing
|
||||
ships remain, try adding coriolis; if this fails, add any ship in
|
||||
shipdata.
|
||||
*/
|
||||
- (void) loadDemoShips
|
||||
{
|
||||
NSEnumerator *enumerator = nil;
|
||||
NSString *key = nil;
|
||||
NSMutableArray *demoShips = nil;
|
||||
|
||||
[_demoShips release];
|
||||
_demoShips = nil;
|
||||
|
||||
demoShips = [[[ResourceManager arrayFromFilesNamed:@"demoships.plist"
|
||||
inFolder:@"Config"
|
||||
andMerge:YES] mutableCopy] autorelease];
|
||||
|
||||
for (enumerator = [demoShips objectEnumerator]; (key = [enumerator nextObject]); )
|
||||
{
|
||||
if (![key isKindOfClass:[NSString class]] || [self shipInfoForKey:key] == nil)
|
||||
{
|
||||
[demoShips removeObject:key];
|
||||
}
|
||||
}
|
||||
|
||||
if ([demoShips count] == 0)
|
||||
{
|
||||
if ([self shipInfoForKey:kDefaultDemoShip] != nil) [demoShips addObject:kDefaultDemoShip];
|
||||
else [demoShips addObject:[[_shipData allKeys] objectAtIndex:0]];
|
||||
}
|
||||
|
||||
_demoShips = [demoShips copy];
|
||||
[[OOCacheManager sharedCache] setObject:_demoShips forKey:kDemoShipsCacheKey inCache:kShipRegistryCacheName];
|
||||
}
|
||||
|
||||
|
||||
- (void) loadCachedRoleProbabilitySets
|
||||
{
|
||||
NSDictionary *cachedSets = nil;
|
||||
NSMutableDictionary *restoredSets = nil;
|
||||
NSEnumerator *roleEnum = nil;
|
||||
NSString *role = nil;
|
||||
|
||||
cachedSets = [[OOCacheManager sharedCache] objectForKey:kRoleWeightsCacheKey inCache:kShipRegistryCacheName];
|
||||
if (cachedSets == nil) return;
|
||||
|
||||
restoredSets = [NSMutableDictionary dictionaryWithCapacity:[cachedSets count]];
|
||||
for (roleEnum = [cachedSets keyEnumerator]; (role = [roleEnum nextObject]); )
|
||||
{
|
||||
[restoredSets setObject:[OOProbabilitySet probabilitySetWithPropertyListRepresentation:[cachedSets objectForKey:role]] forKey:role];
|
||||
}
|
||||
|
||||
_probabilitySets = [restoredSets copy];
|
||||
}
|
||||
|
||||
|
||||
- (void) buildRoleProbabilitySets
|
||||
{
|
||||
NSMutableDictionary *probabilitySets = nil;
|
||||
NSEnumerator *shipEnum = nil;
|
||||
NSString *shipKey = nil;
|
||||
NSDictionary *shipEntry = nil;
|
||||
NSString *roles = nil;
|
||||
NSEnumerator *roleEnum = nil;
|
||||
NSString *role = nil;
|
||||
OOProbabilitySet *pset = nil;
|
||||
NSMutableDictionary *cacheEntry = nil;
|
||||
|
||||
probabilitySets = [NSMutableDictionary dictionary];
|
||||
|
||||
// Build role sets
|
||||
for (shipEnum = [_shipData keyEnumerator]; (shipKey = [shipEnum nextObject]); )
|
||||
{
|
||||
shipEntry = [_shipData objectForKey:shipKey];
|
||||
roles = [shipEntry stringForKey:@"roles"];
|
||||
[self mergeShipRoles:roles forShipKey:shipKey intoProbabilityMap:probabilitySets];
|
||||
}
|
||||
|
||||
// Convert role sets to immutable form, and build cache entry.
|
||||
cacheEntry = [NSMutableDictionary dictionaryWithCapacity:[probabilitySets count]];
|
||||
for (roleEnum = [probabilitySets keyEnumerator]; (role = [roleEnum nextObject]); )
|
||||
{
|
||||
pset = [probabilitySets objectForKey:role];
|
||||
pset = [[pset copy] autorelease];
|
||||
[probabilitySets setObject:pset forKey:role];
|
||||
[cacheEntry setObject:[pset propertyListRepresentation] forKey:role];
|
||||
}
|
||||
|
||||
_probabilitySets = [probabilitySets copy];
|
||||
[[OOCacheManager sharedCache] setObject:cacheEntry forKey:kRoleWeightsCacheKey inCache:kShipRegistryCacheName];
|
||||
}
|
||||
|
||||
|
||||
/* -applyLikeShips:
|
||||
|
||||
Implement like_ship by copying inherited ship and overwriting with child
|
||||
ship values. Done iteratively to report recursive references of arbitrary
|
||||
depth. Also removes and reports ships whose like_ship entry does not
|
||||
resolve, and handles reference loops by removing all ships involved.
|
||||
|
||||
We start with a set of keys all ships that have a like_ships entry. In
|
||||
each iteration, every ship whose like_ship entry does not refer to a ship
|
||||
which itself has a like_ship entry is finalized. If the set of pending
|
||||
ships does not shrink in an iteration, the remaining ships cannot be
|
||||
resolved (either their like_ships do not exist, or they form reference
|
||||
cycles) so we stop looping and report it.
|
||||
*/
|
||||
- (BOOL) applyLikeShips:(NSMutableDictionary *)ioData
|
||||
{
|
||||
NSMutableSet *remainingLikeShips = nil;
|
||||
NSEnumerator *enumerator = nil;
|
||||
NSString *key = nil;
|
||||
NSString *parentKey = nil;
|
||||
NSDictionary *shipEntry = nil;
|
||||
NSDictionary *parentEntry = nil;
|
||||
unsigned count, lastCount;
|
||||
|
||||
// Build set of ships with like_ship references
|
||||
remainingLikeShips = [NSMutableSet set];
|
||||
for (enumerator = [ioData keyEnumerator]; (key = [enumerator nextObject]); )
|
||||
{
|
||||
shipEntry = [ioData objectForKey:key];
|
||||
if ([shipEntry stringForKey:@"like_ship"] != nil)
|
||||
{
|
||||
[remainingLikeShips addObject:key];
|
||||
}
|
||||
}
|
||||
|
||||
count = lastCount = [remainingLikeShips count];
|
||||
while (count != 0)
|
||||
{
|
||||
for (enumerator = [remainingLikeShips objectEnumerator]; (key = [enumerator nextObject]); )
|
||||
{
|
||||
// Look up like_ship entry
|
||||
shipEntry = [ioData objectForKey:key];
|
||||
parentKey = [shipEntry objectForKey:@"like_ship"];
|
||||
if (![remainingLikeShips containsObject:parentKey])
|
||||
{
|
||||
// If parent is fully resolved, we can resolve this child.
|
||||
parentEntry = [ioData objectForKey:parentKey];
|
||||
shipEntry = [self mergeShip:shipEntry withParent:parentEntry];
|
||||
if (shipEntry != nil)
|
||||
{
|
||||
[remainingLikeShips removeObject:key];
|
||||
[ioData setObject:shipEntry forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = [remainingLikeShips count];
|
||||
if (count == lastCount)
|
||||
{
|
||||
// Fail: we couldn't resolve all like_ship entries.
|
||||
OOLog(@"shipData.merge.failed", @"***** ERROR: one or more shipdata.plist entries have like_ship references that cannot be resolved: %@", remainingLikeShips);
|
||||
break;
|
||||
}
|
||||
lastCount = count;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary *) mergeShip:(NSDictionary *)child withParent:(NSDictionary *)parent
|
||||
{
|
||||
NSMutableDictionary *result = [[parent mutableCopy] autorelease];
|
||||
if (result == nil) return nil;
|
||||
|
||||
[result addEntriesFromDictionary:child];
|
||||
[result removeObjectForKey:@"like_ship"];
|
||||
|
||||
return [[result copy] autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) loadAndApplyShipDataOverrides:(NSMutableDictionary *)ioData
|
||||
{
|
||||
NSEnumerator *enumerator = nil;
|
||||
NSString *key = nil;
|
||||
NSDictionary *shipEntry = nil;
|
||||
NSDictionary *overrides = nil;
|
||||
NSDictionary *overridesEntry = nil;
|
||||
|
||||
overrides = [ResourceManager dictionaryFromFilesNamed:@"shipdata-overrides.plist"
|
||||
inFolder:@"Config"
|
||||
mergeMode:MERGE_SMART
|
||||
cache:NO];
|
||||
|
||||
for (enumerator = [overrides keyEnumerator]; (key = [enumerator nextObject]); )
|
||||
{
|
||||
shipEntry = [ioData objectForKey:key];
|
||||
if (shipEntry != nil)
|
||||
{
|
||||
overridesEntry = [overrides objectForKey:key];
|
||||
if (![overridesEntry isKindOfClass:[NSDictionary class]])
|
||||
{
|
||||
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata-overrides.plist entry \"%@\" is not a dictionary, ignoring.", key);
|
||||
}
|
||||
else
|
||||
{
|
||||
shipEntry = [shipEntry dictionaryByAddingEntriesFromDictionary:overridesEntry];
|
||||
[ioData setObject:shipEntry forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
/* -loadAndMergeShipyard:
|
||||
|
||||
Load shipyard.plist, add its entries to appropriate shipyard entries as
|
||||
a dictionary under the key "shipyard", and build list of player ships.
|
||||
Before that, we strip out any "shipyard" entries already in shipdata, and
|
||||
apply any shipyard-overrides.plist stuff to shipyard.
|
||||
*/
|
||||
- (BOOL) loadAndMergeShipyard:(NSMutableDictionary *)ioData
|
||||
{
|
||||
NSEnumerator *enumerator = nil;
|
||||
NSString *key = nil;
|
||||
NSDictionary *shipEntry = nil;
|
||||
NSDictionary *shipyard = nil;
|
||||
NSDictionary *shipyardOverrides = nil;
|
||||
NSDictionary *shipyardEntry = nil;
|
||||
NSDictionary *shipyardOverridesEntry = nil;
|
||||
NSMutableSet *playerShips = nil;
|
||||
|
||||
// Strip out any shipyard stuff in shipdata (there shouldn't be any).
|
||||
for (enumerator = [ioData keyEnumerator]; (key = [enumerator nextObject]); )
|
||||
{
|
||||
shipEntry = [ioData objectForKey:key];
|
||||
if ([shipEntry objectForKey:@"shipyard"] != nil)
|
||||
{
|
||||
[ioData setObject:[shipEntry dictionaryByRemovingObjectForKey:@"shipyard"] forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
shipyard = [ResourceManager dictionaryFromFilesNamed:@"shipyard.plist"
|
||||
inFolder:@"Config"
|
||||
mergeMode:MERGE_BASIC
|
||||
cache:NO];
|
||||
shipyardOverrides = [ResourceManager dictionaryFromFilesNamed:@"shipyard-overrides.plist"
|
||||
inFolder:@"Config"
|
||||
mergeMode:MERGE_SMART
|
||||
cache:NO];
|
||||
|
||||
playerShips = [NSMutableSet setWithCapacity:[shipyard count]];
|
||||
|
||||
// Insert merged shipyard and shipyardOverrides entries.
|
||||
for (enumerator = [shipyard keyEnumerator]; (key = [enumerator nextObject]); )
|
||||
{
|
||||
shipEntry = [ioData objectForKey:key];
|
||||
if (shipEntry != nil)
|
||||
{
|
||||
shipyardEntry = [shipyard objectForKey:key];
|
||||
shipyardOverridesEntry = [shipyardOverrides objectForKey:key];
|
||||
shipyardEntry = [shipyardEntry dictionaryByAddingEntriesFromDictionary:shipyardOverridesEntry];
|
||||
|
||||
shipEntry = [shipEntry dictionaryByAddingObject:shipyardEntry forKey:@"shipyard"];
|
||||
[ioData setObject:shipEntry forKey:key];
|
||||
|
||||
[playerShips addObject:key];
|
||||
}
|
||||
// Else we have a shipyard entry with no matching shipdata entry, which we ignore.
|
||||
}
|
||||
|
||||
_playerShips = [playerShips copy];
|
||||
[[OOCacheManager sharedCache] setObject:[_playerShips allObjects] forKey:kPlayerShipsCacheKey inCache:kShipRegistryCacheName];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) isValidShipEntry:(NSDictionary *)shipEntry name:(NSString *)name
|
||||
{
|
||||
// Quick checks for obvious problems. Not complete validation, just basic sanity checking.
|
||||
if (![shipEntry isKindOfClass:[NSDictionary class]])
|
||||
{
|
||||
OOLog(@"shipData.load.badEntry", @"***** ERROR: the shipdata.plist entry \"%@\" is not a dictionary, ignoring.", name);
|
||||
return NO;
|
||||
}
|
||||
if ([shipEntry stringForKey:@"like_ship"] == nil) // Keys may be inherited, so we only check "root" ships.
|
||||
{
|
||||
if ([[shipEntry stringForKey:@"roles"] length] == 0)
|
||||
{
|
||||
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" specifies no %@, ignoring.", name, @"roles");
|
||||
return NO;
|
||||
}
|
||||
if ([[shipEntry stringForKey:@"model"] length] == 0)
|
||||
{
|
||||
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" specifies no %@, ignoring.", name, @"model");
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (void) mergeShipRoles:(NSString *)roles
|
||||
forShipKey:(NSString *)shipKey
|
||||
intoProbabilityMap:(NSMutableDictionary *)probabilitySets
|
||||
{
|
||||
NSDictionary *rolesAndWeights = nil;
|
||||
NSEnumerator *roleEnum = nil;
|
||||
NSString *role = nil;
|
||||
OOMutableProbabilitySet *probSet = nil;
|
||||
|
||||
/* probabilitySets is a dictionary whose keys are roles and whose values
|
||||
are mutable probability sets, whose values are ship keys.
|
||||
*/
|
||||
|
||||
rolesAndWeights = OOParseRolesFromString(roles);
|
||||
for (roleEnum = [rolesAndWeights keyEnumerator]; (role = [roleEnum nextObject]); )
|
||||
{
|
||||
probSet = [probabilitySets objectForKey:role];
|
||||
if (probSet == nil)
|
||||
{
|
||||
probSet = [OOMutableProbabilitySet probabilitySet];
|
||||
[probabilitySets setObject:probSet forKey:role];
|
||||
}
|
||||
|
||||
[probSet setWeight:[rolesAndWeights floatForKey:role] forObject:shipKey];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OOShipRegistry (Singleton)
|
||||
|
||||
/* Canonical singleton boilerplate.
|
||||
See Cocoa Fundamentals Guide: Creating a Singleton Instance.
|
||||
See also +sharedRegistry above.
|
||||
|
||||
NOTE: assumes single-threaded access.
|
||||
*/
|
||||
|
||||
+ (id) allocWithZone:(NSZone *)inZone
|
||||
{
|
||||
if (sSingleton == nil)
|
||||
{
|
||||
sSingleton = [super allocWithZone:inZone];
|
||||
return sSingleton;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (id) copyWithZone:(NSZone *)inZone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id) retain
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (unsigned) retainCount
|
||||
{
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
|
||||
- (void) release
|
||||
{}
|
||||
|
||||
|
||||
- (id) autorelease
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
@ -385,7 +385,10 @@ static JSBool TimerConstruct(JSContext *context, JSObject *inThis, uintN argc, j
|
||||
function:function
|
||||
this:this];
|
||||
*outResult = [timer javaScriptValueInContext:context];
|
||||
if (delay >= 0) [timer scheduleTimer];
|
||||
if (delay >= 0) // Leave in stopped state if delay is negative
|
||||
{
|
||||
[timer scheduleTimer];
|
||||
}
|
||||
[timer release]; // The JS object retains the ObjC object.
|
||||
|
||||
return YES;
|
||||
|
@ -49,6 +49,7 @@ MA 02110-1301, USA.
|
||||
#import "OOEntityFilterPredicate.h"
|
||||
|
||||
#import "OOCharacter.h"
|
||||
#import "OOShipRegistry.h"
|
||||
|
||||
#import "PlayerEntity.h"
|
||||
#import "PlayerEntityContracts.h"
|
||||
@ -162,6 +163,9 @@ static NSComparisonResult comparePrice(NSDictionary *dict1, NSDictionary *dict2,
|
||||
//Jester Speech End
|
||||
#endif
|
||||
|
||||
// Load ship data
|
||||
[OOShipRegistry sharedRegistry];
|
||||
|
||||
dumpCollisionInfo = NO;
|
||||
next_universal_id = 100; // start arbitrarily above zero
|
||||
for (i = 0; i < MAX_ENTITY_UID; i++)
|
||||
|
Loading…
x
Reference in New Issue
Block a user