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

cylinder_actions.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 "cylinder.h"
00026 #include "log.h"
00027 #include "world.h"
00028 #include "agent.h"
00029 
00030 /** 
00031  * Make the cylinder grow. It wastes energy, in a proportion similar
00032  * to the new area, to make more mass.
00033  */
00034 Cylinder *Cylinder::grow(GrowType type, unsigned short int usedEnergy){
00035   double grow=usedEnergy*0.95;
00036 
00037 
00038   if (type==growHorizontal)
00039     width=sqrt((mass+grow)/(2*M_PI*height));
00040   else{
00041     height=((mass+grow)/(2*M_PI*width*width));
00042   }
00043 
00044   mass=2*M_PI*width*width*height;
00045   energy-=grow;
00046 
00047   return dropEnergy(usedEnergy*0.05);
00048 }
00049 
00050 /**
00051  * Move the cylinder
00052  */
00053 Cylinder *Cylinder::move(MoveType type, unsigned short int usedEnergy){
00054   if (father==NULL){
00055     log <<"Can't move cylinder without parent, energy not wasted"<<endl;
00056   }
00057   
00058   if (type==moveVerticalCW){
00059     //applyForceOnBody(Vector3d(0,usedEnergy,0), Vector3d(0,0,-length/2));
00060     //father->applyForceOnBody(Vector3d(0,-usedEnergy,0), gluePosition);
00061   }
00062   else if (type==moveVerticalCCW){
00063     //applyForceOnBody(Vector3d(0,-usedEnergy,0), Vector3d(0,0,-length/2));
00064     //father->applyForceOnBody(Vector3d(0,usedEnergy,0), gluePosition);
00065   }
00066   else if (type==moveHorizontalCW){
00067     //applyForceOnBody(Vector3d(usedEnergy,0,0), Vector3d(0,0,-length/2));
00068     //    father->applyForceOnBody(Vector3d(-usedEnergy,0,0), gluePosition);
00069   }
00070   else if (type==moveHorizontalCCW){
00071     //applyForceOnBody(Vector3d(-usedEnergy,0,0), Vector3d(0,0,-length/2));
00072     //father->applyForceOnBody(Vector3d(usedEnergy,0,0), gluePosition);
00073   }
00074 
00075   else{
00076     log <<"Wrong movement type ("<<int(type)<<")"<<endl;
00077   }
00078 
00079 
00080   double relation=energy/mass;
00081   double dropE=(log10(relation+1)/(relation*2))*log10(usedEnergy+1);
00082   energy-=(usedEnergy-dropE);
00083   return dropEnergy(dropE);
00084 }
00085 
00086 /**
00087  * Drop a cylinder
00088  */
00089 Cylinder *Cylinder::drop(unsigned char sonId, const char *creationMessage, unsigned long messageSize){
00090   Cylinder *cyl=NULL;
00091   unsigned short int i;
00092   for (i=son.size();i--;)
00093     if (son[i]->cylinderId==sonId){
00094       cyl=son[i];
00095       break;
00096     }
00097 
00098   if (NULL==cyl){
00099     log <<"Can't drop NULL cylinder or it's not a direct son!"<<endl;
00100     return NULL;
00101   }
00102   // FIXME
00103   son.erase(&son[i]);
00104 
00105   World *world=getWorld();
00106   if (NULL==world){
00107     log <<"Can't drop if you are not in a world!!"<<endl;
00108     return NULL;
00109   }
00110 
00111   world->newAgent(cyl, creationMessage, messageSize);
00112 
00113   return NULL;
00114 }
00115 
00116 /**
00117  * A new cylinder is created in this agent with that position (angle
00118  * and height) on it's parent cylinder (this). Total energy of new
00119  * agent is parameter energy
00120  */
00121 
00122 Cylinder *Cylinder::createCylinder(double angle, double atHeight, unsigned short int usedEnergy){
00123   energy-=usedEnergy;
00124 
00125   orientationBase.normalize();
00126 
00127   double h=7*usedEnergy/(16*M_PI*width*width);
00128 
00129   Cylinder *cyl=new Cylinder(world, this, usedEnergy/8, width,h,                
00130                  Vector3d(atHeight, angle, 0), true);
00131 
00132   son.push_back(cyl);
00133 
00134   return NULL;
00135 }
00136 
00137 /**
00138  * Traspases some of own energy to a son's cylinder energy
00139  */
00140 Cylinder *Cylinder::sendEnergyTo(unsigned char son, unsigned short usedEnergy){
00141   Cylinder *cyl=(*this)[son];
00142   if (NULL==cyl)
00143     return NULL;
00144 
00145   energy-=usedEnergy;
00146 
00147   cyl->energy+=usedEnergy;
00148 
00149   return NULL;
00150 }
00151 
00152 
00153 /**
00154  * Creates an energy cylinder of desired energy+mass.
00155  *
00156  * It is created in pseudo-random position in the cylinder surface,
00157  * with a relation between the energy and mass of 7/8
00158  */
00159 Cylinder *Cylinder::dropEnergy(double droppedEnergy){
00160   return NULL;
00161   energy-=droppedEnergy;
00162 
00163   double h=cbrt(droppedEnergy/(576*M_PI));
00164 
00165   /// We calculate the point at what the energy cyl appears.
00166   /*  Vector3d v=referenceAngle.rotate(orientation.getAxis(),energy);     // Rotate it the desired angle
00167   v*=width;                          // As it's normalized multipling
00168                       // it with radius give us a
00169                       // point in the circunference*/
00170   //  Vector3d newPos=getPosition()+(orientation.getAxis()*((cos(energy*mass)+1)*height/2))+v;
00171 
00172   return new Cylinder(world, this, droppedEnergy*7/8, h*6,h, 
00173               Vector3d(cos(energy*mass),energy,0), false);
00174 }
00175 
00176 Cylinder *Cylinder::sendMessage(unsigned long int _agentId, const char *message, unsigned long int size){
00177   if (agent==NULL)
00178     return NULL;
00179 
00180   unsigned long int agentId=agent->getId();
00181 
00182 
00183   /// FIXME!!! I must add noise to the message
00184 
00185   world->addMessage(message,size,agent);
00186 
00187   if (_agentId==agentId)
00188     return NULL;
00189 
00190   Agent *agent=world->getAgent(_agentId);
00191   if (NULL==agent)
00192     return NULL;
00193   agent->receiveMessage(agentId, message, size);
00194 
00195   return NULL;
00196 }
00197 
00198 
00199 /**
00200  * According to desiredAction it realizes an Action
00201  */
00202 Cylinder *Cylinder::performAction(){
00203   Cylinder *ret=NULL;
00204   switch(desiredAction.action){
00205   case growTo:
00206     ret=grow(GrowType(desiredAction.growType), desiredAction.energy);
00207     break;
00208   case newCylinder:
00209     ret=createCylinder(desiredAction.angle, desiredAction.height, desiredAction.energy);
00210     break;
00211   case sendEnergy:
00212     ret=sendEnergyTo(desiredAction.cylinder, desiredAction.energy);
00213     break;
00214   case moveCylinder:
00215     ret=move(desiredAction.moveType, desiredAction.energy);
00216     break;
00217   case dropCylinder:
00218     ret=drop(desiredAction.cylinder, desiredAction.message, desiredAction.messageSize);
00219     break;
00220   case sendMessageAction:
00221     ret=sendMessage(desiredAction.agentId, desiredAction.message, desiredAction.messageSize);
00222     break;
00223   case none:
00224     break;
00225   default:
00226     log <<"desired Action "<<int(desiredAction.action)<<" not implemented yet"<<endl;
00227     break;
00228   }
00229 
00230   desiredAction=Action();
00231   return ret;
00232 }
00233 

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