#include<fstream>
#include "common.hpp"
#include "inet.hpp"
#include "ppm.h"
#include "brain/lin_time.hpp"
shared_ptr<Container> world(new Room(0.0f));//space is black
void loadWorld(const char *filename) {
unsigned char*data;unsigned int width,height;
string east("e");
string west("w");
string north("n");
string south("s");
if (readPPM(filename,&data,&width,&height) ) {
vector<ptrdiff_t>tmprooms(width*height);
vector<shared_ptr<Room> >tmpworld;
for (unsigned int i=0;i<height;++i) {
for (unsigned int j=0;j<width;++j) {
tmprooms[i*width+j]=-1;
unsigned char idata[3];
memcpy(idata,data+3*(j+width*i),3);
if ((idata[0]==0)&&
(idata[1]==0)&&
(idata[2]==0)) {
//no room here
}else {
std::fstream f;
f.open("room.cfg");
float light=(float)(idata[2])/255.0f;
shared_ptr<Room> roomptr(f.fail()?new Farm(light,idata[1]/(float)255,idata[0]/(float)255):new Room(light));
//printf ("r %5d ", tmpworld.size());
tmprooms[i*width+j]=tmpworld.size();
tmpworld.push_back(roomptr);
world->addThing(roomptr);
if (i>0) {
ptrdiff_t index=tmprooms[(i-1)*width+j];
if (index>=0){
tmpworld.back()->exits()[0][north]=tmpworld[index];
tmpworld[index]->exits()[0][south]=tmpworld.back();
}
}
if (j>0) {
ptrdiff_t index=tmprooms[(i)*width+(j-1)];
if (index>=0) {
tmpworld.back()->exits()[0][west]=tmpworld[index];
tmpworld[index]->exits()[0][east]=tmpworld.back();
}
}
char landname[5]={'A'+i%26,'A'+(i/26)%26,
'A'+j%26,'A'+(j/26)%26,
'\0'};
shared_ptr<Thing> landmark(new Landmark(landname));
tmpworld.back()->addThing(landmark);
if (!f.fail()) {
char str[129];
str[128]='\0';
f.width(128);
while(1) {
f>>str;
if (f.fail()) break;
shared_ptr<Thing> landmark(strcmp(str,"food")==0?new Food():(strcmp(str,"poison")==0?static_cast<Thing*>(new Poison()):static_cast<Thing*>(new Landmark(str))));
tmpworld.back()->addThing(landmark);
}
f.close();
}
}
}
}
}
}
extern std::vector<std::pair<GeneticCode,std::pair<float,shared_ptr<Thing> > > >newlyborngrue;
extern std::vector<std::pair<GeneticCode,std::pair<float,shared_ptr<Thing> > > >newlybornsnark;
double etime;
int maxpopgrue,maxpopsnark,minpopgrue,minpopsnark;
int main (int argc, char ** argv) {
InitTime();
maxpopgrue=argc>2?atoi(argv[2]):256;
maxpopsnark=argc>3?atoi(argv[3]):1024;
etime = argc>1?atof(argv[1]):1./128;
minpopgrue=maxpopgrue/8;minpopsnark=maxpopsnark/8;
unsigned short snarkport=argc>5?atoi(argv[3]):7876;
unsigned short grueport=argc>6?atoi(argv[4]):7877;
unsigned short adminport=argc>7?atoi(argv[5]):7878;
INETsocket admin=-1;
INET_startup();
INETsocket adminsocket=INET_listen(adminport);
INETsocket snarksocket=INET_listen(snarkport);
INETsocket gruesocket=INET_listen(grueport);
while(snarksocket==-1) {
snarksocket=INET_listen(++snarkport);
}
while(gruesocket==-1) {
gruesocket=INET_listen(++grueport);
}
while(adminsocket==-1) {
adminsocket=INET_listen(++adminport);
}
if (adminsocket==-1||snarksocket==-1||gruesocket==-1) {
printf ("Failed to bind ports");
exit(1);
}
loadWorld(argc>2?argv[4]:"world.ppm");
shared_ptr<Thing> tmpworld((shared_ptr<Thing>)world);
while(1)
{
double framestarttime=queryTime();
if (INET_BytesToRead(adminsocket)) {
admin=INET_Accept(adminsocket);
}
static int numsnarks=0;
static int numgrues=0;
if (INET_BytesToRead(snarksocket)&&(numsnarks<maxpopsnark||!newlybornsnark.empty())) {
shared_ptr<Thing> newCreature(new Snark(INET_Accept(snarksocket)));
if (newlybornsnark.empty()) {
dynamic_cast<Container*>(world->examineItem(rand()%world->numItems()))->addThing(newCreature);
printf ("Warning, no new snarks needed");
}else {
dynamic_cast<Container*>(newlybornsnark.back().second.second.get())->addThing(newCreature);
newlybornsnark.pop_back();
}
}
if (INET_BytesToRead(gruesocket)&&(numgrues<maxpopgrue||!newlyborngrue.empty())) {
shared_ptr<Thing> newCreature(new Grue(INET_Accept(gruesocket)));
if (newlyborngrue.empty()) {
dynamic_cast<Container*>(world->examineItem(rand()%world->numItems()))->addThing(newCreature);
printf ("Warning, no new grues needed");
}else {
dynamic_cast<Container*>(newlyborngrue.back().second.second.get())->addThing(newCreature);
newlyborngrue.pop_back();
}
}
unsigned int numrooms=world->numItems();
for (unsigned int index=0;index<numrooms;++index) {
world->examineItem(index)->tick(tmpworld,index);
}
double frameendtime=queryTime();
double deltatime=frameendtime-framestarttime;
if (deltatime>etime) {
printf ("Frame took %lf ",deltatime);
}else {
micro_sleep((unsigned int)((etime-deltatime)*1000000.));
}
}
INET_cleanup();
return 0;
}