Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #import "DecisionTreeAgent.h"
00012
00013 @interface DecisionTreeAgent()
00014
00015 -(void)setOptimumRoute;
00016 -(Action)getOptimumAction;
00017
00018 @end
00019
00020 @implementation DecisionTreeAgent
00021
00022 #pragma mark -
00023 #pragma mark Memory Allocation
00024
00028 -(void)dealloc
00029 {
00030 [levelTree release];
00031 [optimumRoute release];
00032 [super dealloc];
00033 }
00034
00035 #pragma mark -
00036 #pragma mark Initialisation
00037
00042 -(id)init
00043 {
00044 self = [super init];
00045
00046 if (self != nil)
00047 {
00048 optimumRoute = [[CCArray alloc] init];
00049 optimumRouteIndex = 0;
00050 currentAction = -1;
00051 }
00052 return self;
00053 }
00054
00055 #pragma mark -
00056
00062 -(Action)selectAction:(State*)_state
00063 {
00064
00065 Action action = -1;
00066
00067
00068 BOOL endConditionReached = (self.state == kStateDead || [_state getGameObject].gameObjectType == kObjectExit);
00069
00070
00071 TreeState* treeState = [[TreeState alloc] initStateForObject:[_state getGameObject]];
00072 CCArray* options = [self calculateAvailableActions:treeState];
00073
00074
00075 int randomNumber = [Utils generateRandomNumberFrom:0 to:(int)(1/kLearningRandomProbability)];
00076 BOOL chooseRandom = (randomNumber == 0) ? chooseRandom = YES : NO;
00077 if(kLearningRandomProbability == 0.0f) chooseRandom = NO;
00078
00079
00080 if(learningMode || chooseRandom)
00081 {
00082 if(!endConditionReached) action = [self chooseRandomAction:options];
00083
00084
00085 if([_state getGameObject] == [levelTree getGameObject] && currentState == nil) currentState = levelTree;
00086 else
00087 {
00088 if(levelTree == nil) levelTree = treeState;
00089 else
00090 {
00091 [treeState setAction:currentAction];
00092 [currentState addChild:treeState];
00093 }
00094
00095
00096 currentState = treeState;
00097 }
00098
00099 currentAction = action;
00100
00101 if(endConditionReached)
00102 {
00103
00104 if(self.state == kStateDead) [treeState setAsLeafNode:kStateDead];
00105 else if([_state getGameObject].gameObjectType == kObjectExit) [treeState setAsLeafNode:kStateWin];
00106
00107
00108 currentState = nil;
00109 }
00110 }
00111
00112 else if(!endConditionReached)
00113 {
00114 action = [self getOptimumAction];
00115
00116
00117 if(action == -1) action = [self chooseRandomAction:options];
00118 }
00119
00120 return action;
00121 }
00122
00127 -(CCArray*)getShortestRoutes
00128 {
00129
00130 CCArray* routes = [CCArray arrayWithCapacity:0];
00131 [levelTree buildRoutes:routes];
00132
00133
00134 if([routes count] == 0) return nil;
00135
00136
00137 CCArray* route = [routes objectAtIndex:0];
00138
00139 for (int i = 1; i < [routes count]; i++)
00140 if([[routes objectAtIndex:i] count] < [route count]) route = [routes objectAtIndex:i];
00141
00142
00143 for (int i = 1; i < [routes count]; i++)
00144 if([[routes objectAtIndex:i] count] > [route count]) [routes removeObjectAtIndex:i];
00145
00146 return routes;
00147 }
00148
00152 -(void)setOptimumRoute
00153 {
00154
00155
00156 CCArray* routes = [self getShortestRoutes];
00157
00158
00159 if([routes count] == 0) return;
00160
00161
00162
00163 NSMutableDictionary* routesWithCosts = [NSMutableDictionary dictionaryWithCapacity:[routes count]];
00164
00165 for (int i = 0; i < [routes count]; i++)
00166 {
00167 CCArray* route = [routes objectAtIndex:i];
00168 int routeCost = 0;
00169
00170 for (int i = 0; i < [route count]; i++)
00171 if([[route objectAtIndex:i] getAction] == kActionDownUmbrella ||
00172 [[route objectAtIndex:i] getAction] == kActionEquipUmbrella ||
00173 [[route objectAtIndex:i] getAction] == kActionLeftHelmet ||
00174 [[route objectAtIndex:i] getAction] == kActionRightHelmet)
00175 routeCost++;
00176
00177 [routesWithCosts setObject:[NSNumber numberWithInt:routeCost] forKey:route];
00178 }
00179
00180
00181
00182
00183 int minimumCost = 999;
00184 CCArray* minimumCostRoute;
00185
00186 for (CCArray* route in routesWithCosts)
00187 {
00188 if([[routesWithCosts objectForKey:route] intValue] < minimumCost)
00189 {
00190 CCLOG(@"Route cost: %i", [[routesWithCosts objectForKey:route] intValue]);
00191 minimumCostRoute = route;
00192 minimumCost = [[routesWithCosts objectForKey:route] intValue];
00193 }
00194 }
00195
00196 CCLOG(@"%@.setOptimumRoute: routes: %i mimumumCost: %i minimumCostRoute: %i", NSStringFromClass([self class]), [routes count], minimumCost, [minimumCostRoute count]);
00197
00198
00199 for (int i = [minimumCostRoute count]-1; i > -1; i--)
00200 [optimumRoute addObject:[minimumCostRoute objectAtIndex:i]];
00201
00202 CCLOG(@"Optimum route is:");
00203 for (int i = 0; i < [optimumRoute count]; i++) CCLOG(@" %@", [Utils getActionAsString:[[optimumRoute objectAtIndex:i] getAction]]);
00204 }
00205
00210 -(Action)getOptimumAction
00211 {
00212 Action action = -1;
00213
00214 if([optimumRoute count] > 0)
00215 {
00216 action = [[optimumRoute objectAtIndex:optimumRouteIndex] getAction];
00217 optimumRouteIndex++;
00218 }
00219
00220 return action;
00221 }
00222
00223 #pragma mark -
00224 #pragma mark Overrides
00225
00230 -(void)onEndConditionReached
00231 {
00232 if(learningMode && respawns < 2) [self setOptimumRoute];
00233 [super onEndConditionReached];
00234 }
00235
00239 -(void)updateDebugLabel
00240 {
00241 [super updateDebugLabel];
00242
00243 if(!(learningMode || self.state == kStateDead || self.state == kStateWin))
00244 {
00245 [debugLabel setString:([optimumRoute count] > 0) ? @"!" : @"?"];
00246 }
00247 }
00248
00249 @end