All Data Structures Files Functions Variables Enumerations Enumerator Properties Defines
/Projects/Cogito/src/GameObjects/CogitoAgents/CogitoAgent.m
Go to the documentation of this file.
00001 //
00002 //  CogitoAgent.m
00003 //  Author: Thomas Taylor
00004 //
00005 //  Base class for machine learning
00006 //
00007 //  20/02/2012: Created class
00008 //
00009 
00010 #import "CogitoAgent.h"
00011 
00012 @implementation CogitoAgent
00013 
00014 #pragma mark -
00015 #pragma mark Initialisation
00016 
00021 -(id)init
00022 {
00023     self = [super init];
00024     
00025     if (self != nil) 
00026     {
00027         respawns = [[LemmingManager sharedLemmingManager] learningEpisodes];
00028         learningMode = YES;
00029     }
00030     return self;
00031 }
00032 
00033 #pragma mark -
00034 
00040 -(Action)selectAction:(State*)_state
00041 {
00042     CCArray* actions = [self calculateAvailableActions:_state];
00043 
00044     // choose a random action
00045     Action action = -1;
00046     if(self.state != kStateDead && [_state getGameObject].gameObjectType != kObjectExit) 
00047         action = [self chooseRandomAction:actions];
00048                 
00049     return action;
00050 }
00051 
00057 -(Action)chooseRandomAction:(CCArray*)_actions
00058 {    
00059     Action action = -1;
00060     
00061     int randomIndex = [Utils generateRandomNumberFrom:0 to:[_actions count]];  
00062     action = [[_actions objectAtIndex:randomIndex] intValue];
00063     
00064     return action;
00065 }
00066 
00073 -(CCArray*)calculateAvailableActions:(State*)_state
00074 {    
00075     GameObject* object = [_state getGameObject];
00076     CCArray* actions = [CCArray arrayWithCapacity:0];
00077     
00078     [actions addObject:[NSNumber numberWithInt:kActionLeft]];
00079     [actions addObject:[NSNumber numberWithInt:kActionRight]];
00080     
00081     if(helmetUses > 0) 
00082     {   
00083         [actions addObject:[NSNumber numberWithInt:kActionLeftHelmet]];
00084         [actions addObject:[NSNumber numberWithInt:kActionRightHelmet]];
00085     }
00086     
00087     // add 'down' action if appropriate
00088     if(object.gameObjectType == kObjectTrapdoor) 
00089     {
00090         [actions addObject:[NSNumber numberWithInt:kActionDown]];
00091         if(umbrellaUses > 0) [actions addObject:[NSNumber numberWithInt:kActionDownUmbrella]];
00092     }
00093     else if(object.gameObjectType == kObjectTerrainEnd && umbrellaUses > 0) 
00094         [actions addObject:[NSNumber numberWithInt:kActionEquipUmbrella]];
00095     
00096     [_state setActions:actions];
00097     return actions;
00098 }
00099 
00105 -(State*)getStateForGameObject:(GameObject*)_object
00106 {
00107     return [[State alloc] initStateForObject:_object];
00108 }
00109 
00110 #pragma mark -
00111 #pragma mark Overrides
00112 
00118 -(void)onObjectCollision:(GameObject*)_object
00119 {    
00120     // need to know if the lemming's fall was fatal (has to be checked before call to super and fallCounter's reset)
00121     BOOL fatalFall = (fallCounter >= ((float)kLemmingFallTime*(float)kFrameRate) && self.state != kStateFloating) ? YES : NO;
00122     
00123     // call the method in super
00124     [super onObjectCollision:_object];
00125         
00126    /* 
00127     * only need to handle two types, 
00128     * rest are dealt with by superclass
00129     */
00130     switch([_object gameObjectType]) 
00131     {
00132         case kObjectTerrainEnd:
00133         case kObjectTrapdoor:
00134             [self takePath:[self selectAction:[self getStateForGameObject:_object]]];
00135             break;
00136             
00137         case kObstacleWater:
00138         case kObstaclePit:
00139         case kObjectExit:
00140             [self selectAction:[self getStateForGameObject:_object]];
00141             break;
00142             
00143         case kObstacleStamper:
00144             if(self.state == kStateDead) [self selectAction:[self getStateForGameObject:_object]];
00145             break;
00146     
00147         case kObjectTerrain:
00148             if(fatalFall) [self selectAction:[self getStateForGameObject:_object]];
00149             break;
00150             
00151         default:
00152             break;
00153     }
00154 }
00155 
00160 -(void)onEndConditionReached
00161 {                
00162     // add the data to AgentStats
00163     int length = [[GameManager sharedGameManager] getGameTimeInSecs] - spawnTime;
00164     if(self.state != kStateDead) [[AgentStats sharedAgentStats] addEpisodeWithLength:length andActions:actionsTaken learningMode:learningMode];
00165     else [[AgentStats sharedAgentStats] addEpisode];
00166     
00167     if(learningMode) 
00168     {   
00169         if(respawns > 1) [self changeState:kStateSpawning];
00170         else 
00171         {
00172             learningMode = NO;
00173             respawns = kLemmingRespawns;
00174             [self changeState:kStateSpawning];
00175         }
00176     }
00177     else if(self.state == kStateDead && respawns > 0) [self changeState:kStateSpawning];
00178     else [[LemmingManager sharedLemmingManager] removeLemming:self];
00179 }
00180 
00184 -(void)updateDebugLabel
00185 {    
00186     [super updateDebugLabel];
00187     [debugLabel setString:(learningMode || self.state == kStateDead || self.state == kStateWin) ? @"" : @"!"];
00188 }
00189 
00190 @end