SPYSpheres
|
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 }