In the overview to this demo (), the difference between 'WrapAround' and 'Strict' borders was described. Here we see this in action. used WrapAround borders; we will modify it to use strict borders.

The main change is simple. In the Model.h file, change the type of space:

class RepastHPCDemoModel{
	int stopAt;
	int countOfAgents;
	repast::Properties* props;
	repast::SharedContext<RepastHPCDemoAgent> context;
	
	RepastHPCDemoAgentPackageProvider* provider;
	RepastHPCDemoAgentPackageReceiver* receiver;

	repast::SVDataSet* agentValues;
        repast::SharedDiscreteSpace<RepastHPCDemoAgent, repast::StrictBorders, repast::SimpleAdder<RepastHPCDemoAgent> >* discreteSpace;

Change the instantiation of this in the initialization code:

RepastHPCDemoModel::RepastHPCDemoModel(std::string propsFile, int argc, char** argv, boost::mpi::communicator* comm): context(comm){
	props = new repast::Properties(propsFile, argc, argv, comm);
	stopAt = repast::strToInt(props->getProperty("stop.at"));
	countOfAgents = repast::strToInt(props->getProperty("count.of.agents"));
	initializeRandom(*props, comm);
	if(repast::RepastProcess::instance()->rank() == 0) props->writeToSVFile("./output/record.csv");
	provider = new RepastHPCDemoAgentPackageProvider(&context);
	receiver = new RepastHPCDemoAgentPackageReceiver(&context);
	
    repast::Point<double> origin(-100,-100);
    repast::Point<double> extent(200, 200);
    
    repast::GridDimensions gd(origin, extent);
    
    std::vector<int> processDims;
    processDims.push_back(2);
    processDims.push_back(2);
    
    discreteSpace = new repast::SharedDiscreteSpace<RepastHPCDemoAgent, repast::StrictBorders, repast::SimpleAdder<RepastHPCDemoAgent> >("AgentDiscreteSpace", gd, processDims, 2, comm);

Change the uses of this in the agent class, beginning in Agent.h:

class RepastHPCDemoAgent{
	
private:
    repast::AgentId   id_;
    double              c;
    double          total;
	
public:
    RepastHPCDemoAgent(repast::AgentId id);
	RepastHPCDemoAgent(){}
    RepastHPCDemoAgent(repast::AgentId id, double newC, double newTotal);
	
    ~RepastHPCDemoAgent();
	
    /* Required Getters */
    virtual repast::AgentId& getId(){                   return id_;    }
    virtual const repast::AgentId& getId() const {      return id_;    }
	
    /* Getters specific to this kind of Agent */
    double getC(){                                      return c;      }
    double getTotal(){                                  return total;  }
	
    /* Setter */
    void set(int currentRank, double newC, double newTotal);
	
    /* Actions */
    bool cooperate();                                                 // Will indicate whether the agent cooperates or not; probability determined by = c / total
    void play(repast::SharedContext<RepastHPCDemoAgent>* context,
              repast::SharedDiscreteSpace<RepastHPCDemoAgent, repast::StrictBorders, repast::SimpleAdder<RepastHPCDemoAgent> >* space);    // Choose three other agents from the given context and see if they cooperate or not
    void move(repast::SharedDiscreteSpace<RepastHPCDemoAgent, repast::StrictBorders, repast::SimpleAdder<RepastHPCDemoAgent> >* space);
    
};

And in Agent.cpp:

void RepastHPCDemoAgent::move(repast::SharedDiscreteSpace<RepastHPCDemoAgent, repast::StrictBorders, repast::SimpleAdder<RepastHPCDemoAgent> >* space){

    std::vector<int> agentLoc;
    space->getLocation(id_, agentLoc);
    
    std::vector<int> agentNewLoc;
    do{
        agentNewLoc.clear();
        agentNewLoc.push_back(agentLoc[0] + (repast::Random::instance()->nextDouble() < .5 ? 1 : -1));
        agentNewLoc.push_back(agentLoc[1] + (repast::Random::instance()->nextDouble() < .5 ? 1 : -1));
        if(!space->bounds().contains(agentNewLoc)) std::cout << " INVALID: " << agentNewLoc[0] << "," << agentNewLoc[1] << std::endl;
        
    }while(!space->bounds().contains(agentNewLoc));
    
    space->moveTo(id_,agentNewLoc);
    
}

In addition to the change to the method signature of the 'move' method, we must additionally ensure that the agent does not move out of bounds. With WrapAround borders, moving beyond the global boundaries will position you on the other 'side' of the space. (In fact, moving to a location very far outside the borders will result in the agent being placed back within the known borders, as if the space repeated endlessly.) However, with Strict Borders, it is possible to select a location 'outside' the space. Repast HPC will throw an error in this event. To deal with this, in this demo we have allowed the agents to walk randomly, and if they attempt to step outside of the permitted boundaries, they are redirected back inside. The check on this is the space->bounds().contains() method.

Run this and inspect the output; you should not see any agent near the edge of the global boundaries (e.g. -100, -100) playing any non-local agent. It is still possible for an agent at an interior boundary to play a non-local agent, of course.