0
votes

I read with interest this post to StackOverflow: How to Make a Basic Finite State Machine in Objective-C

I used this as a basis to build my state-machine for a simple football game. I have states Defend, Attack, Stoppage, Neutral. I have created the state Machine and it will print out with NSLog "Now Entering State Defend" etc.

Now I would like to pass in a reference to my Football Team to the state Machine, such that I can make my team do something based on the state. Ie if its Defend, I can send my players to stand next to an opponent.

Ive tried many different ways but all end in syntax errors. Id appreciate a push in the right direction

TeamState.h Note the Errors Im getting in the comments

@class TeamState;

#import <Foundation/Foundation.h>
#import "FootballTeam.h"

@protocol TeamStateProt 

-(void) enterTeamState:(TeamState*)team;
-(void) executeTeamState:(TeamState*)team;
-(void) exitTeamState:(TeamState*)team;

@end


@interface TeamState : NSObject{
    id<TeamStateProt> currentTeamState;

    id<TeamStateProt> Stoppage;
    id<TeamStateProt> Neutral;
    id<TeamStateProt> Defend;
    id<TeamStateProt> Attack;

    FootballTeam *footballTeam;  //ERROR Unknown Type name FootballTeam 
}

@property (nonatomic, retain) id<TeamStateProt> currentTeamState;
@property (nonatomic, retain) id<TeamStateProt> Stoppage;
@property (nonatomic, retain) id<TeamStateProt> Neutral;
@property (nonatomic, retain) id<TeamStateProt> Defend;
@property (nonatomic, retain) id<TeamStateProt> Attack;

- (id)initWithFootBallTeam:(FootballTeam*) team; //Error Expected a Type
-(void)update;
-(void)changeState:(id<TeamStateProt>) newState;
-(void)executeState:(id<TeamStateProt>) State;
@end

TeamState.m

#import "TeamState.h"
#import "FootballTeam.h"
#import "Stoppage_TS.h"
#import "Neutral_TS.h"
#import "Defend_TS.h"
#import "Attack_TS.h"


@implementation TeamState 

@synthesize currentTeamState;
@synthesize Stoppage, Neutral, Defend, Attack;

- (id)init
{
    self = [super init];
     if (self) {
        // Initialization code here.
        id<TeamStateProt>  s = [[Stoppage_TS alloc] init];
        self.Stoppage = s;

        id<TeamStateProt>  n = [[Neutral_TS alloc] init];
        self.Neutral = n;

        id<TeamStateProt>  d = [[Defend_TS alloc] init];
        self.Defend = d;

        id<TeamStateProt>  a = [[Attack_TS alloc] init];
        self.Attack = a;

        self.currentTeamState = n;
        [self.currentTeamState enterTeamState:self];
        [self executeState:self.currentTeamState];
    }

    return self;
}

- (id)initWithFootBallTeam:(FootballTeam*) team
{
    self = [super init];
    if (self) {
        // Initialization code here.
        id<TeamStateProt>  s = [[Stoppage_TS alloc] init];
        self.Stoppage = s;


        id<TeamStateProt>  n = [[Neutral_TS alloc] init];
        self.Neutral = n;

        id<TeamStateProt>  d = [[Defend_TS alloc] init];
        self.Defend = d;

        id<TeamStateProt>  a = [[Attack_TS alloc] init];
        self.Attack = a;

        self.currentTeamState = n;
        [self.currentTeamState enterTeamState:self];
        [self executeState:self.currentTeamState];

        footballTeam = team;
    }

    return self;
}

-(void)changeState:(id<TeamStateProt>) newState{
    NSLog(@"Changing State");
    if (newState != nil) {
        NSLog(@"Changing a state which isn't nil");
        [self.currentTeamState exitTeamState:self];
        self.currentTeamState = newState;
        [self.currentTeamState enterTeamState:self];
        [self executeState:self.currentTeamState];
    }

}

-(void)executeState:(id<TeamStateProt>) State{
    [self.currentTeamState executeTeamState:self];
}

// Each update, execute the execute state on the current team state
-(void)update{
    [self executeState:self.currentTeamState];
}
@end

FootballTeam.h

#import <Foundation/Foundation.h>
#import "Player.h"
#import "TeamState.h"
#import "Football.h"

typedef enum  {
    Home,
    Away
} TeamType;

@interface FootballTeam : NSObject{
    Player *ReceivingPlayer;    //Player to receive the ball
    Player *ClosestToBall;      //Player closest to the ball
    Player *ControllingPlayer;  //Player who has the ball can be NULL
    Player *SupportingPlayer;   //Player in a position to receive the ball

    NSMutableArray *players;    //Array of all the Players on this team

    TeamState *state;           //Current state of the teams state machine

    TeamType type;              //Defines if Home team or Away team
}

@property (nonatomic) TeamType type;
@property(nonatomic, retain) TeamState *state;

-(void) sendPlayersToHome;
-(Player*) playerClosestToBall:(Football*) ball;
-(BOOL) areAllPlayersAtHome;

@end
1

1 Answers

1
votes

You've got circular references. You're importing TeamState.h in FootballTeam.h and vice versa.

To avoid this, import the .h files in the .m files only, and add forward declarations in the .h files.

So, in TeamState.h:

@class FootballTeam;

And move the import to TeamState.m

The same in FootballTeam.