Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

client.cc

Go to the documentation of this file.
00001 /*
00002   svas_server -- virtual World Server of Svas
00003   Copyright (c) 2001, 2002 David Moreno Montero
00004  
00005  
00006   This program is free software; you can redistribute it and/or modify
00007   it under the terms of the GNU General Public License as published by
00008   the Free Software Foundation; either version 2 of the License, or
00009   (at your option) any later version.
00010  
00011   This program is distributed in the hope that it will be useful, but
00012   WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   General Public License for more details.
00015  
00016   You should have received a copy of the GNU General Public License
00017   along with this program; if not, write to the Free Software
00018   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00019   02111-1307, USA.  
00020 
00021 */
00022 
00023 #include <thread.h>
00024 #include <math.h>
00025 #include "client.h"
00026 #include "agent.h"
00027 #include "log.h"
00028 #include "world.h"
00029 #include "message.h"
00030 
00031 #ifndef M_PI
00032 # define M_PI           3.14159265358979323846 
00033 #endif
00034 
00035 Client::~Client(){
00036   world->clientOut(this);
00037 }
00038 
00039 Client::Client(ost::TCPSocket &sock, World *w) : baseClient(sock,w){
00040   initialize();
00041 }
00042 
00043 void Client::Run(void){
00044   log <<"Run Agent Client"<<endl;
00045   
00046   try{
00047     while(1){
00048       Message msg(stream);    
00049       switch(msg.type){
00050       case messageNewCylinder:
00051     newCylinder(msg);
00052     break;
00053       case messageGrow:
00054     grow(msg);
00055     break;
00056       case messageSendEnergy:
00057     sendEnergy(msg);
00058     break;
00059       case messageMove:
00060     move(msg);
00061     break;
00062       case messageDrop:
00063     dropCylinder(msg);
00064     break;
00065       case messageSendMessage:
00066     sendMessage(msg);
00067     break;
00068       case messageLog:
00069     clientLog(msg);
00070     break;
00071       case messageEndOfTurn:
00072     endOfTurn(msg);
00073     break;
00074       default:
00075     log <<"Unknown message type "<<msg.type<<endl;
00076       }
00077     }
00078   }
00079   catch(...){      
00080     log <<"Exception caught! Exiting client!"<<endl;
00081     alive=false;
00082     return;          
00083   }
00084 
00085   alive=false;
00086   log <<"End of Agent Client"<<endl;
00087 }
00088 
00089 void Client::initialize(){
00090   /** Check client version */
00091   char version;
00092   version=stream->get();
00093   log<<"Client protocol version is "<<int(version)<<"."<<endl;
00094   if (version!=0x00){
00095     log <<"Invalid version!!!"<<endl;
00096     alive=false;
00097     return;
00098   }
00099 
00100   /** Get the name */
00101   char c;  name="";
00102   c=stream->get();
00103   while(c!=0){
00104     name+=c;
00105     *stream>>c;
00106   }
00107   log <<"Client name: "<<name<<endl;
00108 
00109   /** We Create an agent */
00110 
00111   Agent *ag=new Agent(this,Point3d(0,0,15),NULL,0);
00112   log <<"First agent of client in "<<(*ag)[0]->getPosition().toString()<<endl;
00113   world->newAgent(ag);
00114 }
00115 
00116 /**
00117  * Make a cylinder appear near any other cylinder
00118  */
00119 void Client::newCylinder(Message &msg){
00120   if (msg.size!=4){
00121     log <<"Bad newCylinder message"<<endl;
00122     return;
00123   }
00124   unsigned char cyl=msg.umsg[0];
00125   double angle=(((unsigned char)msg.umsg[1])*2*M_PI)/256.0;
00126   double height=((unsigned char)msg.umsg[2])/255.0;
00127   unsigned short energy=msg.umsg[3];
00128 
00129   //  log <<"Create cylinder, father "<<long(cyl)<<" angle: "<<angle<<" height "<<height<<" energy: "<<energy<<endl;
00130   
00131   Agent *agent=world->getAgent(msg.organismId);
00132   Cylinder *cylinder=NULL;
00133   if (NULL!=agent)
00134     cylinder=(*agent)[cyl];
00135   if (cylinder==NULL){
00136     log <<"Cylinder or agent does not exist!"<<int(cyl)<<endl;
00137     msg.size=0;
00138   }
00139   else{
00140     if (cylinder->getEnergy()>=energy){
00141       
00142       //// This is the REAL call, all the rest are checks'n locks
00143       cylinder->newIntention(Action(angle, height, energy));
00144       ////
00145       
00146       msg.size=1;
00147       msg.msg[0]=agent->getCylinderCount();
00148     }
00149     else{ /// Cylinder can't create son
00150       msg.size=0;
00151     }
00152   }
00153   
00154   msg.petition=false;
00155   //log <<msg.toString()<<endl;
00156   msg.sendTo(stream);
00157   stream->sync();
00158 }
00159 
00160 /**
00161  * Make a cylinder get droped from agent, includes the creation
00162  * message of the new agent son
00163  */
00164 void Client::dropCylinder(Message &msg){
00165   if (msg.size<1){
00166     log <<"Bad dropCylinder message"<<endl;
00167     return;
00168   }
00169   unsigned char cyl=msg.umsg[0];
00170 
00171   Agent *agent=world->getAgent(msg.organismId);
00172   Cylinder *cylinder=NULL;
00173   if (agent!=NULL)
00174     cylinder=(*agent)[cyl];
00175 
00176   if (cylinder==NULL){
00177     log <<"Cylinder or agent does not exist!"<<int(cyl)<<endl;
00178     msg.size=0;
00179   }
00180   else{
00181     cylinder=cylinder->getFather();
00182     if (cylinder==NULL){
00183       log <<"Can't drop 1st cylinder of agent"<<endl;
00184       msg.size=0;
00185     }
00186     else{
00187       cylinder->newIntention(Action(cyl, msg.msg+1, msg.size-1));
00188     }
00189   }
00190 
00191   msg.petition=false;
00192   msg.sendTo(stream);
00193   stream->sync();
00194 }
00195 
00196 
00197 /**
00198  * Send a message to another agent, and maybe some clients can get it
00199  * from the air. This message is sent by cylinder n. zero, always.
00200  */
00201 void Client::sendMessage(Message &msg){
00202   if (msg.size<4){
00203     log <<"Bad sendMessage message"<<endl;
00204     return;
00205   }
00206 
00207   Agent *agent=world->getAgent(msg.organismId);
00208 
00209   long agentId=((msg.umsg[0]&0x0FF)<<24)+((msg.umsg[1]&0x0FF)<<16)+
00210                ((msg.umsg[2]&0x0FF)<<8 )+((msg.umsg[3]&0x0FF));
00211   char *message=&(msg.msg[4]);
00212 
00213   Cylinder *cyl=(*agent)[0];
00214   if (NULL==cyl)
00215     log <<"this agent cant' send messages"<<endl;
00216   else
00217     cyl->newIntention(Action(agentId, msg.size-4, message));
00218 
00219   msg.size=0;
00220   msg.petition=false;
00221   msg.sendTo(stream);
00222   stream->sync();
00223 }
00224 
00225 
00226 /**
00227  * Send some energy from a parent cylinder to one of his sons, or from
00228  * son to his father
00229  */
00230 void Client::sendEnergy(Message &msg){
00231   if (msg.size!=3){
00232     log <<"Bad sendEnergy message"<<endl;
00233     return;
00234   }
00235   unsigned char cyl1=msg.umsg[0];
00236   unsigned char cyl2=msg.umsg[1];
00237   unsigned char energy=msg.umsg[2];
00238 
00239   //log <<"sendEnergy father: "<<long(cyl1)<<" son: "<<long(cyl2)<<" energy: "<<long(energy)<<endl;
00240   
00241   Agent *agent=world->getAgent(msg.organismId);
00242   Cylinder *cylinder1=NULL,*cylinder2=NULL;
00243   if (NULL!=agent){
00244     cylinder1=(*agent)[cyl1];
00245     cylinder2=(*agent)[cyl2];
00246   }
00247   if ((cylinder1==NULL)||(cylinder2==NULL)){
00248     log <<"Cylinder(s) or agent does not exist!"<<int(cyl1)<<" "<<int(cyl2)<<endl;
00249     msg.size=0;
00250   }
00251   else{
00252     if (cylinder1->dist(cylinder2)==1)   // cyl1 is the father
00253       if (cylinder1->getEnergy()>=energy)
00254     cylinder1->newIntention(Action(cyl2, energy));
00255       else
00256     msg.size=0;
00257     else if (cylinder2->dist(cylinder1)==1) // no, it's cyl2
00258       if (cylinder2->getEnergy()>=energy)
00259     cylinder2->newIntention(Action(cyl1, energy));
00260       else
00261     msg.size=0;
00262     else
00263       msg.size=0;
00264   }
00265 
00266   msg.petition=false;
00267   msg.sendTo(stream);
00268   stream->sync();
00269 }
00270 
00271 /** 
00272  * Make the client grow a little bit
00273  */
00274 void Client::grow(Message &msg){
00275   if (msg.size!=2){
00276     log <<"Bad grow message"<<endl;
00277     return;
00278   }
00279   unsigned char cyl=msg.umsg[0];
00280   GrowType type=((msg.umsg[1]>>7)&1) ? growVertical : growHorizontal;
00281   unsigned short int energy=msg.umsg[1]&0x07F;
00282   
00283   // Use the same msg to response...
00284   msg.petition=false;
00285   
00286   Agent *agent=world->getAgent(msg.organismId);
00287   
00288   Cylinder *cylinder=NULL;
00289   if (NULL!=agent)
00290     cylinder=(*agent)[cyl];
00291   if (cylinder==NULL){
00292     log <<"Cylinder or agent does not exist!"<<int(cyl)<<endl;
00293     msg.size=0;
00294   }
00295   else{
00296     if (cylinder->getEnergy()>=energy){
00297       
00298       //// This is the REAL call, all the rest are checks'n locks
00299       cylinder->newIntention(Action(energy, type));
00300       ////
00301       
00302     }
00303     else{ /// Cylinder can't grow
00304       msg.size=0;
00305     }
00306   }
00307   
00308   msg.petition=false;
00309   msg.sendTo(stream);
00310   stream->sync();
00311 }
00312 
00313 /**
00314  * Moves a cylinder, around it's father
00315  */
00316 void Client::move(Message &msg){
00317   if (msg.size!=3){
00318     log <<"Bad move message"<<endl;
00319     return;
00320   }
00321   unsigned char cyl=msg.umsg[0];
00322   MoveType type=moveUnknown;
00323   switch((msg.msg[1]>>6)&3){
00324   case 0:
00325     type=moveVerticalCW;
00326     break;
00327   case 1:
00328     type=moveVerticalCCW;
00329     break;
00330   case 2:
00331     type=moveHorizontalCW;
00332     break;
00333   case 3:
00334     type=moveHorizontalCCW;
00335     break;
00336   }
00337   unsigned short int energy=((msg.umsg[1]&0x03F)<<8)+msg.umsg[2];
00338   
00339   // Use the same msg to response...
00340   msg.petition=false;
00341   
00342   Agent *agent=world->getAgent(msg.organismId);
00343   
00344   Cylinder *cylinder=NULL;
00345   if (NULL!=agent)
00346     cylinder=(*agent)[cyl];
00347   if (cylinder==NULL){
00348     log <<"Cylinder or agent does not exist!"<<int(cyl)<<endl;
00349     msg.size=0;
00350   }
00351   else{
00352     if (cylinder->getEnergy()>=energy){
00353       //// This is the REAL call, all the rest are checks'n locks
00354       cylinder->newIntention(Action(energy, type));
00355       ////
00356       
00357     }
00358     else{ /// Cylinder can't grow
00359       msg.size=0;
00360     }
00361   }
00362   
00363   msg.petition=false;
00364   msg.sendTo(stream);
00365   stream->sync();
00366 }
00367 
00368 
00369 /**
00370  * Log a message
00371  */
00372 void Client::clientLog(Message &msg){
00373   string str="";
00374   for (unsigned int i=0;i<msg.size;i++)
00375     str+=char(msg.msg[i]);
00376   log <<"Log: "<<str<<endl;
00377   
00378   // And we response
00379   msg.size=0;
00380   msg.petition=false;
00381   msg.sendTo(stream);
00382   stream->sync();
00383 }
00384 
00385 
00386 void Client::endOfTurn(Message &msg){
00387   msg.petition=false;
00388   msg.sendTo(stream);
00389   stream->sync();
00390   dontWalk();
00391 }

Generated on Mon Jun 17 19:53:43 2002 for Svas Server by doxygen1.2.16