35@interface OORoleSet (OOPrivate)
37- (id)initWithRolesAndProbabilities:(NSDictionary *)dict;
44+ (instancetype) roleSetWithString:(NSString *)roleString
46 return [[[
self alloc] initWithRoleString:roleString] autorelease];
50+ (instancetype) roleSetWithRole:(NSString *)role probability:(
float)probability
52 return [[[
self alloc] initWithRole:role probability:probability] autorelease];
55- (id)initWithRoleString:(NSString *)roleString
57 NSDictionary *dict =
nil;
60 return [
self initWithRolesAndProbabilities:dict];
64- (id)initWithRole:(NSString *)role probability:(
float)probability
66 NSDictionary *dict =
nil;
68 if (role !=
nil && 0 <= probability)
70 dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:probability] forKey:role];
72 return [
self initWithRolesAndProbabilities:dict];
78 [_roleString autorelease];
79 [_rolesAndProbabilities autorelease];
86- (NSString *)description
88 return [NSString stringWithFormat:@"<%@ %p>{%@}", [
self class], self, [
self roleString]];
92- (BOOL)isEqual:(
id)other
94 if ([other isKindOfClass:[
OORoleSet class]])
96 return [_rolesAndProbabilities isEqual:[other rolesAndProbabilities]];
104 return [_rolesAndProbabilities hash];
108- (id)copyWithZone:(NSZone *)zone
111 return [
self retain];
115- (NSString *)roleString
117 NSArray *roles =
nil;
118 NSEnumerator *roleEnum =
nil;
119 NSString *role =
nil;
121 NSMutableString *result =
nil;
124 if (_roleString ==
nil)
127 result = [NSMutableString string];
128 roles = [
self sortedRoles];
129 for (roleEnum = [roles objectEnumerator]; (role = [roleEnum nextObject]); )
131 if (!first) [result appendString:@" "];
134 [result appendString:role];
136 probability = [
self probabilityForRole:role];
137 if (probability != 1.0f)
139 [result appendFormat:@"(%g)", probability];
143 _roleString = [result copy];
150- (BOOL)hasRole:(NSString *)role
152 return role !=
nil && [_rolesAndProbabilities objectForKey:role] !=
nil;
156- (float)probabilityForRole:(NSString *)role
158 return [_rolesAndProbabilities oo_floatForKey:role defaultValue:0.0f];
162- (BOOL)intersectsSet:(
id)set
164 if ([
set isKindOfClass:[
OORoleSet class]])
set = [set roles];
165 else if (![
set isKindOfClass:[NSSet
class]])
return NO;
167 return [[
self roles] intersectsSet:set];
175 _roles = [[NSSet alloc] initWithArray:[_rolesAndProbabilities allKeys]];
181- (NSArray *)sortedRoles
183 return [[_rolesAndProbabilities allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
187- (NSDictionary *)rolesAndProbabilities
189 return _rolesAndProbabilities;
195 NSEnumerator *roleEnum =
nil;
196 NSString *role =
nil;
197 float prob, selected;
199 selected =
randf() * _totalProb;
202 if ([_rolesAndProbabilities
count] == 0)
return nil;
204 for (roleEnum = [_rolesAndProbabilities keyEnumerator]; (role = [roleEnum nextObject]); )
206 prob += [_rolesAndProbabilities oo_floatForKey:role];
207 if (selected <= prob)
break;
211 role = [[
self roles] anyObject];
212 OOLog(
@"roleSet.anyRole.failed",
@"Could not get a weighted-random role from role set %@, returning unweighted selection %@. TotalProb: %g, selected: %g, prob at end: %f",
self, role, _totalProb, selected, prob);
218- (id)roleSetWithAddedRoleIfNotSet:(NSString *)role probability:(
float)probability
220 NSMutableDictionary *dict =
nil;
222 if (role ==
nil || probability < 0 || ([
self hasRole:role] && [
self probabilityForRole:role] == probability))
224 return [[
self copy] autorelease];
227 dict = [[_rolesAndProbabilities mutableCopy] autorelease];
228 [dict setObject:[NSNumber numberWithFloat:probability] forKey:role];
229 return [[[[
self class] alloc] initWithRolesAndProbabilities:dict] autorelease];
233- (id)roleSetWithAddedRole:(NSString *)role probability:(
float)probability
235 NSMutableDictionary *dict =
nil;
237 if (role ==
nil || probability < 0 || [
self hasRole:role])
239 return [[
self copy] autorelease];
242 dict = [[_rolesAndProbabilities mutableCopy] autorelease];
243 [dict setObject:[NSNumber numberWithFloat:probability] forKey:role];
244 return [[[[
self class] alloc] initWithRolesAndProbabilities:dict] autorelease];
248- (id)roleSetWithRemovedRole:(NSString *)role
250 NSMutableDictionary *dict =
nil;
252 if (![
self hasRole:role])
return [[
self copy] autorelease];
254 dict = [[_rolesAndProbabilities mutableCopy] autorelease];
255 [dict removeObjectForKey:role];
256 return [[[[
self class] alloc] initWithRolesAndProbabilities:dict] autorelease];
262@implementation OORoleSet (OOPrivate)
264- (id)initWithRolesAndProbabilities:(NSDictionary *)dict
266 NSEnumerator *roleEnum =
nil;
267 NSString *role =
nil;
277 if (
self ==
nil)
return nil;
283 assert(_roles ==
nil && _roleString ==
nil);
285 NSMutableDictionary *tDict = [[dict mutableCopy] autorelease];
286 float thargProb = [dict oo_floatForKey:@"thargon" defaultValue:0.0f];
288 if ( thargProb > 0.0f && [dict objectForKey:
@"EQ_THARGON"] ==
nil)
290 [tDict setObject:[NSNumber numberWithFloat:thargProb] forKey:@"EQ_THARGON"];
291 [tDict removeObjectForKey:@"thargon"];
294 _rolesAndProbabilities = [tDict copy];
296 for (roleEnum = [dict keyEnumerator]; (role = [roleEnum nextObject]); )
298 prob = [dict oo_floatForKey:role defaultValue:-1];
301 OOLog(
@"roleSet.badValue",
@"Attempt to create a role set with negative or non-numerical probability for role %@.", role);
317 NSMutableDictionary *result =
nil;
318 NSArray *tokens =
nil;
320 NSString *role =
nil;
322 NSScanner *scanner =
nil;
325 if (
string ==
nil)
return nil;
328 count = [tokens count];
331 result = [NSMutableDictionary dictionaryWithCapacity:count];
334 for (i = 0; i !=
count; ++i)
336 role = [tokens objectAtIndex:i];
339 if ([role rangeOfString:
@"("].location != NSNotFound)
341 scanner = [[NSScanner alloc] initWithString:role];
342 [scanner scanUpToString:@"(" intoString:&role];
343 [scanner scanString:@"(" intoString:NULL];
344 if (![scanner scanFloat:&probability]) probability = 1.0f;
351 if (0 <= probability && ![role hasPrefix:
@"["])
353 [result setObject:[NSNumber numberWithFloat:probability] forKey:role];
357 if ([result
count] == 0) result =
nil;
#define OOLog(class, format,...)
NSDictionary * OOParseRolesFromString(NSString *string)
NSDictionary * OOParseRolesFromString(NSString *string)
NSMutableArray * ScanTokensFromString(NSString *values)