I am creating a program that involves a simple agent navigating a grid world to discover food. I am having trouble creating a unique class for the agent (which contains data members that represent its perception of the world - direction of the smell of the food, a visual 5x7 field which contains barracades and other world objects, and the agent's energy ). The agent receives these in the form of a single string from a socket buffer and then sends its response based on it's reasoning resulting from the current state of the environment (which changes every time it makes a decision- so it is a stimulus-response agent).

I am very new at programming (probably obviously) and would appreciate some code critique and/or ideas on how to make this program better. I am specifically having troubles with moving my existing implementation to an agent class in a .h file. I also would like to include the 2d vector representing the agent's visual field in that class and maybe add data members to it which represent front, back, left, right etc. Thank you for taking the time to look : )

/* agentnavigation
 */
 
using namespace std;

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <iomanip>

#include "connection.cpp"
#include "agent.h"



int main( ) 
{
	string role;
	int sock;
	/* establishing role as base */
	role = "base\n";
	
	/* to connect to the environment of Maeden, connect to the Madenport server 
	by creating an intance of the socket class and sending your role.  
	Socket constructer returns the agent's id.						*/
	sock = connect(role);	
	//
	string Message = Receive(sock);
/**************** agent information *********************/
	char id = Message.at(0); 
	char dir = Message.at(2);
	
	stack<char> inventory;
	char gd[35]; 
	int it = 0; //iterator for grid
	char ground;
	string message("");

	//put this into agent class
	stack<char> s;
	char* myposition;
	int endlines = 0;
	/* get input */
	for (int i = 1; i < Message.size(); i++)	
	{
		if ( Message.at(i) == '\n') { endlines++; }
		if ( Message.at(i) == '"' && !s.empty())  { s.pop(); }
		
		 if ( Message.at(i) == '"' && s.empty() ) 
			{ 
				s.push( Message.at(i)); 
				if( endlines == 2 && Message.at(i+1) != '(' && Message.at(i+1) != ')') { inventory.push( Message.at(i+1) );}

				if( endlines == 3 && Message.at(i+1) != '(' && Message.at(i+1) != ')' ) //fill grid array up with data
				{
						{
							gd[it] = (Message.at(i+1));
							it++;
						}
				}	
			}
		/*  arrive at the point in the buffer which shows what is on the ground */
		if ( endlines == 4 && Message.at(i+1) != '(' ) 
				{
					if (Message.at(i+1) == ')') ground = ' ';
					else ground = Message.at(i+1); 
				}
	}
	
//	cout << "inventory of size " << inventory.size() << " contains: " << inventory.top() << '\n';
	cout << "grid of size " << it << ":" << '\n';
//	for ( int i=0; i< it; i++)
//	{
//		cout << i << gd[i] << '\n';
//	}
	
//	cout << "id: " << id << '\n';
//	cout << "direction: " << dir << '\n';
//	cout << "ground: "" << ground << """<<'\n';
/********** visual field ****************/

	vector<vector<char> > grid ( 5, vector<char> (7) );
	int i = 0;
	while (i < it)
	{
		for (int k=0; k<5; k++)
		{
			for (int j = 0; j < 7; ++j)
			{
				grid[k][j] = gd[i];
				i++;
			}
		}
	}


  for ( int i = 0; i < 5; i++ ) 
	{
		for ( int j = 0; j < 7; j++ )
		cout << '|' << grid[i][j] <<'|';
		cout<<'\n';
	}

/********** end of agent attribute intialization****************/

Send("r\n", sock);


	
	//HELP: having trouble with using agent class functions
	//agent mouse(role , id);
	//mouse.interpret( Receive(sock) );
	//mouse.respond();

		Receive(sock);
		//cout << "Received sock...in whileloop before Send() \n";

	
	return 0;
}
/*
 *  agent.h
 *
 *
 */
#ifndef AGENT_H
#define AGENT_H
 
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
using namespace std;
 
class agent
{
public:
	agent();
	agent (string role, char i);
	~agent();
	
	void initagent(string r, char i) ; 
	string role() const { return myrole; }
	
	struct world
	{
		char gradient; 
		bool passedCheese;
		
		char ground;
		bool onCheese;
		 /*** HELP : I would like to consolidate these into a visual grid
		  representation structure using the vector matrix from the 
		  main (	vector< vector<char> > grid;)	***/
		  
		/* bool blockedLeft;
		bool blockedRight;
		bool blockedFront; */

		char inventory; 
	};
	
	/** HELP: knowlege base structure representation( functions consisting of if/else statements ??) **/
	
	/*return response functions */
	
	string myrole;
	char myId;
	char energy;
};
#endif /*"agent.h"*/
Comments
Thanks for using code tags correctly the first time :)

You have several things going here. You have the agent class. Within that class you have a world class, which is the world as the agent sees it. Is that any different from the world as it really is? In particular, the 5 x 7 grid? Basically, I am wondering whether world can be its own class, independent of agent. I see on line 35 a gd array, which I assume is the 5 x 7 grid. Any reason you want to store the grid as a vector of vectors in the world class rather than an array? I'm just thinking it may be better to have a separate world class which also stores the data as a char array. Presumably each coordinate of the grid can store an empty space, a wall, or a piece of food. And each piece of food has a certain smell intensity? The smell from the agent's point of view is based on the distance to the food and the smell intensity? Perhaps a food class that has a coordinate and an intensity.

Figure out the "rules" of the game, what needs to be stored, what each object type is, and what data members there are. From there, design some function prototypes. You'll likely have many classes. Tackle the sockets later and keep them as separate from the other classes as possible. If there is no need to have a vector of vectors, I would get rid of them

Thank you for responding VernonDozier : ). I've modified the program a bit. The agent class contains a structure called SENSE which will contain the 2d vector (I had found out how to create the grid using the vector and not a simple array so stuck with the vector for now) which represents the agent's 5x7 current view of the world. The SPOT structure represents each spot in the grid. I would like to store the 2d vector as a data member in the SENSE structure but right now it doesn't like me. Eventually I will add a map class (within the agent) which will update with information derrived as the agent navigates the world.
The agent's only objective is to find a single piece of food stored in the world. The agent can only sense the direction of the food relative to its on orientation in the world- this is represented by the 'gradient' member which stores either 'f', 'b', 'l', or 'r' for directions: forward, back, left, or right. These are also the key characters for the agent's navigation commands. Other sensory data members updated each time a move is made are; char onGround (stores what is underneath the agent), bool blocked()(stores whether there is a wall blocking the spot or not), char agent(later on there will be multiple agents in the world which help the first find the food, this member will store the agent's id if there is an agent on the spot), bool onCheese ( true if the agent is on the same coordinate as the food), and inventory is a stack of items the agent has picked up(useful for more involved navigation with keys to doors and the like).
The world itself is already implemented in java and the main.cpp connects to it's server via socket(all of which is implemented in a "connection.cpp" file) .
Right now I am still having trouble integrating the agent class with the main program. I have attached a snapshot of my x-code compile errors. Thanks for your help!

Here is the new code:

/*
 *  agent.h
 *
 */
#ifndef AGENT_H
#define AGENT_H
 
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
using namespace std;

#define COLS	       5
#define ROWs	7

struct SPOT
{
	char obj; // contains object on the SPOT
	char agent; // agent id if there is an agent on the SPOT
	bool blocked;
	
	//refer to neighboring SPOTs on map maybe will make a map class when I can figure  out how to make member functions read these
	SPOT* north;
	SPOT* south;
	SPOT* east;
	SPOT* west;
};


struct SENSE : public SPOT
{
	char gradient; 		
	bool onCheese;
	char inventory;
	char onGround;
	
};
 
class agent: public SENSE : public SPOT
{
public:

	/**utility functions**/
	string role() const { return myRole; }
	char id() const {return myId; }
	char energy() const { return myEnergy; }

	
	string myRole;
	char myId;
	char myEnergy;
	
	struct SENSE : public SPOT
	{
		char gradient; 		
		bool onCheese;
		char inventory;
		char onGround;		
		SPOT* me;
		SPOT* myLeft;
		SPOT* myRight;
		SPOT* myBack;
		SPOT* myFront;
		  //function updateSenses is having trouble reading this
		vector<vector<SPOT> > map();
	};
	
void updateSenses (string Message) 
	{
		myId = Message.at(0); 
		gradient = Message.at(2);
		stack<char> inventory;
		char gd[35]; 
	 
		string message("");
		
		stack<char> s;
		int endlines = 0;
		int it = 0;
		/* get input */
		for (int i = 1; i < Message.size(); i++)	
		{
			if ( Message.at(i) == '\n') { endlines++; }
			if ( Message.at(i) == '"' && !s.empty())  { s.pop(); }
			
			 if ( Message.at(i) == '"' && s.empty() ) 
				{ 
					s.push( Message.at(i)); 
					if( endlines == 2 && Message.at(i+1) != '(' && Message.at(i+1) != ')') { inventory.push( Message.at(i+1) );}
					
					/* what do we see? */
					if( endlines == 3 && Message.at(i+1) != '(' && Message.at(i+1) != ')' ) //fill grid array up with data
					{
							{
								gd[it] = (Message.at(i+1));
								it++;
							}
					}	
				}
			/* what's on the ground? */
			if ( endlines == 4 && Message.at(i+1) != '(' ) 
					{
						if (Message.at(i+1) == ')') onGround = ' ';
						else onGround = Message.at(i+1); 
					}
		}
	vector< vector<SPOT> > view (5, vector<SPOT> (7)); 
		int i = 0;
		while (i < it)
		{
			for ( int k = 0; k < 5; k++ )
			{
				for (int j = 0; j < 7; ++j)
				{
					if (gd[i] == " ") { view[k][j].blocked = false;  }//if empty space, SPOT is not blocked
					if (gd[i]== "0") // if this is me
					{
						me = view[k][j];
						myRight = view[k][j+1];
						myLeft = view[k][j-1];
						myFront = view[k-1][j];
						myBack = view[k+1][j];
					}
					//north, south.. etc implemented in larger grid
					i++;
				}
			}
		}
//cout grid
	  for ( int i = 0; i < 5; i++ ) 
		{
			for ( int j = 0; j < 7; j++ )
			cout << '|' << view[i][j] <<'|';
			cout<<'\n';
		}
	}
	
//string chooseWisely()
//{
//		/*** this will contain all the if/else statements
//}

};
#endif /*"agent.h"*/

/*
 *  maedenagent
 *
 *  by Aaryn Smith
 *  Copyright 2009 __WestmontCollege__. All rights reserved.
 *
 */
 

#include <netinet/in.h> //do i need this?
#include <sys/socket.h> //do i need this?
#include <arpa/inet.h> //do i need this?
using namespace std;

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <iomanip>

#include "connection.cpp"
#include "agent.h"



int main( ) 
{
	/* to connect to the environment of Maeden, connect to the Madenport server 
	by creating an intance of the socket class and sending your role.  
	Socket constructer returns the agent's id.						*/
	int sock;
	string role = "base\n";
	sock = connect(role);	
	string Message = Receive(sock);
	agent mouse;
	mouse.updateSenses(Message);


	//put this into agent class
	
/********** end of agent attribute intialization****************/

	Send("r\n", sock);
	Receive(sock);

	
	return 0;
}
Attachments Picture_1.png 59.65 KB

I've never mixes structs and classes like that, so I changed the structs to classes and made everything public when I tested them out. It probably doesn't matter though, since there's not much difference between a struct and a class aside from public versus private default permissions (that may be the ONLY difference. I'm not sure.). You can change them back from classes to structs as you had before. I commented a lot out to get it to compile, and this caused it to not compile:

class agent: public SENSE : public SPOT

You already have this:

class SENSE : public SPOT

so it seems you should change this:

class agent: public SENSE : public SPOT

to this:

class agent: public SENSE

since you've already declared that SENSE inherits from SPOT. Therefore you don't need to do it again.

It's not the only problem, but it's one that needed fixing.

As far as this code goes:

#include <netinet/in.h> //do i need this?
#include <sys/socket.h> //do i need this?
#include <arpa/inet.h> //do i need this?

I believe those are Linux socket libraries, so wherever you are handling the sockets, you'll need to include them.

Thanks VD. Is there a glaring error that is making my updateSenses function not able to read the data members? -these are the main errors that my compiler is giving me. I guess I also have to overload the << operator for the SPOT class. Would it help to post my connection file as well?

This article has been dead for over six months. Start a new discussion instead.