SPYSpheres
ZRCamera.cpp
Go to the documentation of this file.
00001 #include <string.h>
00002 #include <math.h>
00003 #include "ZRGame.h"
00004 #include "ZRGameInternal.h"
00005 
00006 /*#ifdef ZRSIMULATION
00007 #include "mex.h"
00008 #define GAME_TRACE(arg) DEBUG(arg)
00009 #else
00010 #define GAME_TRACE(arg)
00011 #endif*/
00012 
00013 void ZeroRoboticsGameImpl::initCamera()
00014 {
00015   challInfo.camera.memoryFilled = 0;
00016   challInfo.camera.memorySize = CAMERA_DEFAULT_MEMORY;
00017   challInfo.camera.cameraOn = true;
00018   challInfo.camera.cameraBlocked = false;
00019 }
00020 
00021 void ZeroRoboticsGameImpl::disableCamera()
00022 {
00023   challInfo.camera.cameraOffTime = apiImpl.api->getTime();
00024   challInfo.camera.cameraOn = false;
00025   GAME_TRACE(("[%d] camera OFF | ", apiImpl.api->getTime()));
00026 }
00027 
00028 void ZeroRoboticsGameImpl::activateCamera()
00029 {
00030   challInfo.camera.cameraOn = true;
00031   GAME_TRACE(("[%d] camera ON | ", apiImpl.api->getTime()));
00032 }
00033 
00034 
00035 void ZeroRoboticsGameImpl::memoryLoss()
00036 {
00037   memset(challInfo.camera.memory,0,CAMERA_MAX_MEMORY*sizeof(Picture));  // erase memory
00038   challInfo.camera.memoryFilled = 0;                                    // reset counter
00039   GAME_TRACE(("[%d] memory CLEARED | ", apiImpl.api->getTime()));
00040 }
00041 
00042 /********************camera functions************************/
00043 int ZeroRoboticsGame::getMemoryFilled() const
00044 {
00045   return pimpl.challInfo.camera.memoryFilled;
00046 }
00047 
00048 int ZeroRoboticsGame::getMemorySize()
00049 {
00050   return pimpl.challInfo.camera.memorySize;
00051 }
00052 
00053 float ZeroRoboticsGame::takePic()
00054 {
00055   if(!pimpl.challInfo.camera.cameraOn) {
00056     return 0;
00057   }
00058   return pimpl.takePicImpl();
00059 }
00060 
00061 float ZeroRoboticsGame::getPicPoints()
00062 {
00063   if(!pimpl.challInfo.camera.cameraOn) {
00064         return 0;
00065     }
00066 
00067   if (!pimpl.tryToUseEnergy(ENERGY_COST_GET_PIC_POINTS)) {
00068     return 0;
00069   }
00070 
00071   return pimpl.picPointsImpl();
00072 }
00073 
00074 bool ZeroRoboticsGame::isCameraOn()
00075 {
00076   return pimpl.challInfo.camera.cameraOn;
00077 }
00078 
00079 float ZeroRoboticsGameImpl::picPointsImpl()
00080 {
00081   // check if other in light or grey zone, camera is on, the spheres are facing
00082   bool isCameraOn = challInfo.camera.cameraOn;
00083   bool isFacingOtherResult = isFacingOther();
00084   bool isOppNotInDarkZone = !sphereInDark(challInfo.other.zrState);
00085   bool myMirror = challInfo.me.mirrorTime != 0 && challInfo.me.mirrorTime + ITEM_MIRROR_DURATION > challInfo.currentTime;
00086   bool otherMirror = challInfo.other.mirrorTime != 0 && challInfo.other.mirrorTime + ITEM_MIRROR_DURATION > challInfo.currentTime;
00087   float picturePointValue = 0;
00088   if (isCameraOn && isFacingOtherResult && isOppNotInDarkZone && !myMirror)
00089   {
00090     float bet[3], distance;
00091     mathVecSubtract(bet, challInfo.me.zrState, challInfo.other.zrState, 3);
00092     distance = mathVecMagnitude(bet, 3);
00093 
00094     if (distance < PHOTO_MIN_DISTANCE) {
00095       GAME_TRACE(("Not a good shot: too close to the other satellite | "));
00096       return 0.0;
00097     }
00098     picturePointValue = 2.0 + 0.1/(distance - PHOTO_MIN_DISTANCE + 0.1);
00099     if(otherMirror){
00100       #ifdef ZR2D
00101       picturePointValue = 0;
00102       #else
00103       picturePointValue = -1*picturePointValue;
00104       #endif
00105       GAME_TRACE(("Not a good shot: Opposing mirror active %f|", picturePointValue));
00106     }
00107 
00108   }
00109   else if(!isCameraOn){
00110     GAME_TRACE(("Not a good shot: camera off |"));
00111   }
00112   else if(myMirror){
00113     GAME_TRACE(("Not a good shot: my mirror's in the way |"));
00114   }
00115   else if(!isFacingOtherResult) {
00116         GAME_TRACE(("Not a good shot: not facing the other satellite | "));
00117     }
00118   else if(!isOppNotInDarkZone){
00119     GAME_TRACE(("Not a good shot: opponent in dark zone |"));
00120   }
00121   return picturePointValue;
00122 }
00123 
00124 /**
00125 * Returns the score value of the picture, or 0 if taking
00126 * the picture failed
00127 */
00128 float ZeroRoboticsGameImpl::takePicImpl()
00129 {
00130 
00131   challInfo.me.score += 0.01f;
00132   GAME_TRACE(("[%d] attempting to take picture... ", challInfo.currentTime));
00133 
00134   bool enoughSpace = challInfo.camera.memoryFilled < challInfo.camera.memorySize;
00135 
00136 
00137   // uses the energy even if the picture can't be taken
00138   // (if not enough space or not facing other sphere)
00139   bool usedEnergy = tryToUseEnergy(ENERGY_COST_TAKE_PICTURE);
00140 
00141   float pictureValue = picPointsImpl();
00142 
00143   if(enoughSpace && usedEnergy && pictureValue != 0)     // check if it can take a picture
00144   {
00145     challInfo.camera.tookPicture = true;
00146     // apply score modifiers etc
00147     challInfo.me.score += 0.1f;         // Very small value. Subject to change.
00148     challInfo.camera.memory[challInfo.camera.memoryFilled].picStored = true;
00149 
00150     challInfo.camera.memory[challInfo.camera.memoryFilled].value = pictureValue;
00151     // End of scoring
00152 
00153     challInfo.camera.memory[challInfo.camera.memoryFilled].round = 1;
00154 
00155 
00156     challInfo.camera.memoryFilled++;
00157 
00158 
00159     GAME_TRACE(("[%d] took picture (round %d) valued %4.2f points | ", apiImpl.api->getTime(), challInfo.camera.memory[challInfo.camera.memoryFilled-1].round, challInfo.camera.memory[challInfo.camera.memoryFilled-1].value));
00160 
00161   }
00162    else if(!enoughSpace && pictureValue != 0 ){
00163     GAME_TRACE(("Failed to take a picture: memory filled up | "));
00164   }
00165    else if(!usedEnergy && pictureValue != 0 ){
00166     GAME_TRACE(("Failed to take a picture: not enough energy | "));
00167   }
00168 
00169   disableCamera();
00170 
00171   return pictureValue;
00172 }
00173 
00174 bool ZeroRoboticsGameImpl::isFacingPos(float position[]) {
00175   float relativePos[3];
00176   mathVecSubtract(relativePos, position, challInfo.me.zrState, 3);
00177   mathVecNormalize(relativePos, 3);
00178   //Check if generally pointing at the other satellite (dot product) and
00179   //if within a small margin of error (to account for noise)
00180   //after bugfix, increased allowed error to 0.25f from 0.0575f
00181   // MAX_FACING_ANGLE = 0.968912f is cosf(0.25f)
00182   bool facing = mathVecInner(&challInfo.me.zrState[ZR_ATT_X], relativePos, 3) > MAX_FACING_ANGLE;
00183   return facing;
00184 }
00185 
00186 bool ZeroRoboticsGameImpl::isFacingOther() {
00187   bool facing = isFacingPos(challInfo.other.zrState);
00188   //GAME_TRACE(("isFacingOther: facing = %d| ", facing));
00189   return facing;
00190 }
00191 
00192 bool ZeroRoboticsGame::isFacingOther(){
00193   return pimpl.isFacingOther();
00194 }
00195 
00196 bool ZeroRoboticsGameImpl::isFacingEarth() {
00197   float earth [3];
00198   memcpy(earth, EARTH, 3 * sizeof(float));
00199   return mathVecInner(&challInfo.me.zrState[ZR_ATT_X], earth, 3) > MAX_FACING_ANGLE;
00200 }
00201 
00202 float ZeroRoboticsGame::uploadPics(){
00203   float totalScore = 0.0;
00204   if(!pimpl.tryToUseEnergy(ENERGY_COST_UPLOAD_PICTURES)) return 0.0;
00205 
00206   GAME_TRACE(("[%d] trying to upload... ", apiImpl.api->getTime()));
00207 
00208   // Need to check that the SPHERE isn't going too fast to upload.
00209   float speed = mathVecMagnitude(&pimpl.challInfo.me.zrState[9],3);
00210   if (speed>UPLOAD_ANG_VEL)
00211   {
00212     GAME_TRACE(("Rotating too fast, Upload Failed. Speed=%2.4f",speed));
00213     return 0.0;
00214   }
00215 
00216 // Need to check if the SPHERE is pointing towards earth before running the code to upload pictures.
00217 #ifndef ZR2D
00218   if (!pimpl.isFacingEarth())
00219   {
00220   return totalScore;
00221   GAME_TRACE(("Not Facing Earth, Upload Failed. "));
00222   }
00223 #endif
00224   pimpl.challInfo.camera.uploadedPictures = true;
00225   pimpl.disableCamera();            // For only three seconds.
00226   for (unsigned int i = 0; i < pimpl.challInfo.camera.memoryFilled; i++)
00227     {
00228   if (pimpl.challInfo.camera.memory[i].picStored == true)
00229   {
00230     pimpl.challInfo.camera.memory[i].picStored = false;
00231           pimpl.challInfo.me.score += pimpl.challInfo.camera.memory[i].value;
00232     totalScore  += pimpl.challInfo.camera.memory[i].value;
00233           GAME_TRACE(("uploaded picture for %4.2f points | ", pimpl.challInfo.camera.memory[i].value));
00234        }
00235     }
00236   pimpl.challInfo.camera.memoryFilled = 0;
00237 
00238 
00239   return totalScore;
00240 }