示例#1
0
bool AI::run()
{
  realLight=(playerID())?player1Light():player0Light();
  cout<<"Turn: "<<turnNumber()<<" Player: "<<playerID()<<" Light: "<<realLight<<endl;
  cout<<"Plants: "<<plants.size()<<endl;
  if(plants.size()<2)
  {
    return true;
  }
  //if the queue is empty
  if(que.empty())
  {
  //  cout<<"First time on this turn"<<endl;
    resetDataStructures();
    buildQueue();
  }
  //cout<<"Queue Size: "<<que.size()<<endl;
  //runs once
  return doActions();
  /*
  while(!que.empty())
  {
    que.pop();
  }
  return true;
  */
  //otherwise
  //return doActions();
  /*
  while(!doActions()){};
  return true;
  */
}
示例#2
0
文件: game.cpp 项目: wheein/MiHaJong
void TableProtoScene::ScoreBoard::renderRank() {
	PlayerRankList rankList = utils::calcRank(GameStatus::gameStat());
	const ArgbColor color =
		(rankList[playerID()] == 1) ? ledColorRed : // トップは赤
		(rankList[playerID()] == (GameStatus::gameStat()->chkGameType(SanmaT) ? 3 : 4) ? ledColorOrange : // ラスはオレンジ
		ledColorGreen); // その他は緑で表示

	renderNumeral(RankPosX, RankPosY, rankList[playerID()], color); // その他は緑で表示
	if ((myTimer.currTime() % 1000000 < 500000) && (GameStatus::gameStat()->CurrentPlayer.Active == playerID()))
		renderNumeral(RankPosX, RankPosY, digitDecimal, color);
}
示例#3
0
Unit* AI::findNearestTarget(Bot& actor)
{
  int x=actor.x();
  int y=actor.y();
  int size = actor.size();
  int bestDist = INT_MAX;
  Unit* target=NULL;
  // If it can attack or it cannot heal
  //bool attacker = actor.damage()>0 || actor.buildRate()==0;
  bool attacker =true;
  // loops through all bots
  for(unsigned int b=0;b<bots.size();b++)
  {
    // if I want to attack, and it is an enemy or I want to heal and its an ally
    if((attacker && (playerID()!=bots[b].owner()) || !(attacker && (playerID()==bots[b].owner()))))
    {
      int tempDist = distance(x,y,size, bots[b].x(),bots[b].y(),bots[b].size());
      if(tempDist < bestDist)
      {
        bestDist=tempDist;
        target=&(bots[b]);
      }
    }
  }
  
  // if I am an attacker, include walls and frames
  if(attacker)
  {
    for(unsigned int w=0;w<walls.size();w++)
    {
      int tempDist = distance(x,y,size, walls[w].x(),walls[w].y(),1);
      if(tempDist < bestDist)
      {
        bestDist=tempDist;
        target=&(walls[w]);
      }
    }
    for(unsigned int f=0;f<frames.size();f++)
    {
      if(frames[f].owner() != playerID())
      {
        int tempDist = distance(x,y,size, frames[f].x(),frames[f].y(),frames[f].size());
        if(tempDist < bestDist)
        {
          bestDist=tempDist;
          target=&(frames[f]);
        }
      }
    }
  }  
  return target;
}
示例#4
0
void AI::objectCheck()
{
  cout<<"--Base AI variables--"<<endl;
  cout<<"turnNumber\t"<<turnNumber()<<endl;
  ///Player Number; either 0 or 1
  cout<<"playerID\t"<<playerID()<<endl;
  ///What number game this is for the server
  cout<<"gameNumber\t"<<gameNumber()<<endl;
  ///Player 0's time remaining
  cout<<"player0Time\t"<<player0Time()<<endl;
  ///Player 1's time remaining
  cout<<"player1Time\t"<<player1Time()<<endl;
  ///Player 0's name
  cout<<"player0Name\t"<<player0Name()<<endl;
  ///Player 1's name
  cout<<"player1Name\t"<<player1Name()<<endl;
  ///The cost of a pirate
  cout<<"pirateCost\t"<<pirateCost()<<endl;
  ///The cost of a ship
  cout<<"shipCost\t"<<shipCost()<<endl;
  cout<<"portCost\t"<<portCost()<<endl;
  cout<<"boardX\t"<<boardX()<<endl;
  cout<<"baordY\t"<<boardY()<<endl;
  cout<<"--Object counts--"<<endl;
  cout<<"Pirates : "<<pirates.size()<<endl;
  displayPirates();
  cout<<"Ports   : "<<ports.size()<<endl;
  displayPorts();
  cout<<"Ships   : "<<ships.size()<<endl;
  displayShips();
  cout<<"Tiles   : "<<tiles.size()<<endl;
  displayTiles();
  cout<<"Treasure: "<<treasures.size()<<endl;
//  displayTreasure();
}
示例#5
0
void AI::resetDataStructures()
{
  //ignore the boundaries
  for(unsigned int x=1;x<canSpawnHere.size()-1;x++)
  {
    for(unsigned int y=1;y<canSpawnHere[x].size()-1;y++)
    {
      //return them all to true
      canSpawnHere[x][y]=true;
      canSpreadHere[x][y]=true;
    }
  }
  //for every plant
  for(unsigned int i=0;i<plants.size();i++)
  {
    //you can't build here
    canSpawnHere[plants[i].x()+1][plants[i].y()+1]=false;
    //if its my plant
    if(plants[i].ownerID() == playerID())
    {
      canSpreadHere[plants[i].x()+1][plants[i].y()+1] = false;
    }
  }
  notActing.resize(plants.size());
  for(unsigned int i=0;i<notActing.size();i++)
  {
    notActing[i]=false;
  }
}
示例#6
0
文件: game.cpp 项目: wheein/MiHaJong
void TableProtoScene::ScoreBoard::Render() {
#ifndef _WIN32
	if (!initialized) {
		objInit();
		initialized = true;
	}
#endif /*_WIN32*/
	RECT rect = {0, 0, PanelWidth, PanelHeight};
	SpriteRenderer::instantiate(myDevice)->ShowSprite(texture, (int)xpos, (int)ypos,
		PanelWidth, PanelHeight, 0xffffffff, &rect, 0, 0, &myMatrix);
	if ((playerID() >= 0) && (playerID() < (GameStatus::gameStat()->chkGameType(SanmaT) ? 3 : 4))) {
		renderWind();
		renderRank();
		renderScore();
		renderName();
	}
}
示例#7
0
//This function is run once, before your first turn.
void AI::init()
{
  //get the opponent's ID
  if(playerID() == 0)
  {
    enemyAI_ID = 1;
  }
  else
  {
    enemyAI_ID = 0;
  }
}
示例#8
0
//This function is run once, before your first turn.
void AI::init()
{
  //Determines which player you are
  if(playerID() == 0)
  {
    enemyAI_ID = 1;
  }
  else
  {
    enemyAI_ID = 0;
  }
}
示例#9
0
文件: game.cpp 项目: wheein/MiHaJong
std::tuple<unsigned, unsigned, signed, signed> TableProtoScene::ScoreBoard::scoreInfo(ScoreMode scoreMode) {
	if (scoreMode == scoreChip) {
		const int& chipAmount = GameStatus::gameStat()->Player[playerID()].playerChip;
		return std::make_tuple(abs(chipAmount), 0, 0, (chipAmount > 0) ? 1 : (chipAmount < 0) ? -1 : 0);
	} else {
		const LargeNum playerScoreDiff = GameStatus::gameStat()->Player[playerID()].PlayerScore - GameStatus::gameStat()->statOfMine().PlayerScore;
		const LargeNum* const score = (scoreMode == scoreDiff) ?
			&playerScoreDiff :
			&(GameStatus::gameStat()->Player[playerID()].PlayerScore);
		const int digit[10] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
		int sign;
		if      (*score > LargeNum::fromInt(0)) sign =  1;
		else if (*score < LargeNum::fromInt(0)) sign = -1;
		else                                    sign =  0;
		for (int i = DigitGroups - 1; i >= 0; --i) {
			for (int j = ((i == DigitGroups - 1) ? 9 : 7); j >= 0; --j) {
				if ((GameStatus::gameStat()->gameType & RichiMJ) && (i == 0) && (j == 4)) {
					return std::make_tuple(abs(score->digitGroup[0] / 100), 0, 0, sign);
				}
				else if ((GameStatus::gameStat()->gameType & GuobiaoMJ) && (i == 0) && (j == 2)) {
					return std::make_tuple(abs(score->digitGroup[0]), 0, 0, sign);
				}
				else if (score->digitGroup[i] / digit[j]) {
					unsigned digitCode = i * 8 + j; unsigned digits;
					if (j >= 2) {
						digits = abs(score->digitGroup[i] / digit[j - 2]);
					} else {
						assert(i > 0);
						digits = abs(score->digitGroup[i] * digit[2 - j]) + abs(score->digitGroup[i - 1] / digit[j + 6]);
					}
					if (digitCode % 4 == 3)
						return std::make_tuple(digits, digitCode / 4 + 1, -1, sign);
					else
						return std::make_tuple(digits, digitCode / 4, digitCode % 4, sign);
				}
			}
		}
	}
	throw _T("ScoreBoard::scoreInfo() : Unexpected control flow");
}
示例#10
0
QString GameDBStorage::GetSetClause(MSqlBindings &bindings) const
{
    QString playerID(":SETPLAYERID");
    QString colTag(":SET" + GetColumnName().toUpper());

    QString query("gameplayerid = " + playerID + ", " +
                  GetColumnName() + " = " + colTag);

    bindings.insert(playerID, parent.getGamePlayerID());
    bindings.insert(colTag, user->GetDBValue());

    return query;
}
示例#11
0
文件: game.cpp 项目: wheein/MiHaJong
void TableProtoScene::ScoreBoard::renderWind() {
	if ((myTimer.currTime() % 1000000 >= 500000) && (GameStatus::gameStat()->CurrentPlayer.Active == playerID())) return; // ツモ番の時は表示を点滅させる
	const seatAbsolute wind = GameStatus::gameStat()->playerwind(playerID());
	if (GameStatus::gameStat()->chkGameType(Sanma4) && (wind == sNorth)) return; // 四人三麻の時の抜け番は何も表示しないようにする
	RECT rect = {
		static_cast<int32_t>(WindCharX + WindCharWidth * ((int)wind    )), WindCharY,
		static_cast<int32_t>(WindCharX + WindCharWidth * ((int)wind + 1)), WindCharY + WindCharHeight
	};
	SpriteRenderer::instantiate(myDevice)->ShowSprite(texture, (int)xpos + WindPosX, (int)ypos + WindPosY,
		WindCharWidth, WindCharHeight,
		(wind == sEast) ? ledColorRed : ledColorGreen, // 「東」のみ赤で、それ以外を緑で表示すればわかりやすいと思うのでそうする
		&rect, 0, 0, &myMatrix);
}
示例#12
0
//This function is called each time it is your turn.
//Return true to end your turn, return false to ask the server for updated information.
bool AI::run()
{
  for(int i = 0; i < bots.size(); i++)
  {
    if(bots[i].owner() == playerID())
    {
      bots[i].move(direction[rand()%4]);
    }
    if(bots[i].buildRate())
    {
      bots[i].build(types[rand() % types.size()], bots[i].x() + 1, bots[i].y(), 1);
    }
  }
  return true;
}
示例#13
0
文件: game.cpp 项目: wheein/MiHaJong
void TableProtoScene::ScoreBoard::renderScore() {
	unsigned digits, unitcode; signed decimalPos, sign;
	ArgbColor color;
	ScoreMode scoreMode = getScoreMode();

	std::tie(digits, unitcode, decimalPos, sign) = scoreInfo(scoreMode);
	switch (scoreMode) {
	case scorePoints:
		if (utils::isAboveBase(GameStatus::gameStat(), playerID()))
			color = ledColorRed; // 浮いていれば赤
		else
			color = ledColorGreen; // 沈みは緑
		break;
	case scoreDiff: case scoreChip:
		if      (sign ==  1) color = ledColorRed;
		else if (sign == -1) color = ledColorGreen;
		else                 color = ledColorOrange;
		break;
	}

	if ((scoreMode != scoreDiff) || (playerID() != GameStatus::gameStat()->PlayerID)) {
		if (sign == 1)
			renderNumeral(ScorePosX - NumCharWidth    , ScorePosY, digitPlus         , color);
		else if (sign == -1)
			renderNumeral(ScorePosX - NumCharWidth    , ScorePosY, digitMinus        , color);
		if ((unitcode != 0) || (digits / 100))
			renderNumeral(ScorePosX                   , ScorePosY, digits       / 100, color);
		if ((unitcode != 0) || (digits / 100) || (digits % 100 / 10))
			renderNumeral(ScorePosX + NumCharWidth    , ScorePosY, digits % 100 / 10 , color);
		renderNumeral(    ScorePosX + NumCharWidth * 2, ScorePosY, digits % 10       , color);
		if (unitcode != 0)
			renderNumeral(ScorePosX + NumCharWidth * decimalPos, ScorePosY, digitDecimal, color);
		if ((GameStatus::gameStat()->gameType & RichiMJ) && (scoreMode != scoreChip))
			renderScoreUnit(unitcode, color);
	}
}
示例#14
0
//RUSKI FUNCTIONS
void AI::update()
{
  cout << "CLEARING CREATURE ARRAYS" << endl;
  myCreatures.erase(myCreatures.begin(), myCreatures.end());
  enemyCreatures.erase(enemyCreatures.begin(), enemyCreatures.end());

  cout << "BUILDING CREATURE ARRAYS" << endl;
  for(int i = 0; i < creatures.size(); i++)
  {
    //MY CREATURES
    if( creatures[i].owner() == playerID() )
    {
      myCreatures.push_back( RuskiCre(&creatures[i]) );
    }
    //ENEMY CREATURES
    else
    {
      enemyCreatures.push_back( &creatures[i] );
    }
  }
  cout << "ENDED CREATURE ARRAY CREATION" << endl;
}
示例#15
0
//This function is called each time it is your turn.
//Return true to end your turn, return false to ask the server for updated information.
bool AI::run()
{
  cout<<"Turn: "<<turnNumber()<<endl;
  vector<int> builders, uncombined, actors;
  for(unsigned int b=0;b<bots.size();b++)
  {
    // if it is my bot
    if(bots[b].owner()==playerID() && bots[b].partOf()==0)
    {
			bots[b].talk( "Hi there, I'm you're robot" );
      if(bots[b].buildRate()>0 && builders.size()<4 && bots[b].size()==1)
      {
        builders.push_back(b);
      }
      else if(bots[b].size()==1)
      {
        uncombined.push_back(b);
      }
      else
      {
        actors.push_back(b);
      }
    }
  }
  // starting builders
  if(builders.size()<4)
  {
    
    for(unsigned int b=0;b<builders.size();b++)
    {
      int x=bots[builders[b]].x()+xMod[playerID()*2 +1];
      int y=bots[builders[b]].y()+yMod[playerID()*2 +1];
      bots[builders[b]].build(types[1], x, y, 1);
    }    
  }
  // if there are 4 builders
  if(builders.size()==4)
  {
    // check if the builders are in their correct locations
    for(unsigned int b=0;b<builders.size();b++)
    {
      int dir=1;
      if(bots[builders[b]].y()==9)
      {
        bots[builders[b]].move("up");
      }
      else if(bots[builders[b]].y()==10)
      {
        bots[builders[b]].move("down");
      }
      if(bots[builders[b]].y()==8)
      {
        dir = 2;
      }
      else if(bots[builders[b]].y()==11)
      {
        dir = 0;
      }
      int x=bots[builders[b]].x()+xMod[dir];
      int y=bots[builders[b]].y()+yMod[dir];
      if(bots[builders[b]].actions()>0)
      {
        // builds 4 different guys
        bots[builders[b]].build(types[(built/4+b)%types.size()], x, y, 1);
        built++;
      }
    }
  }
  if(uncombined.size()==4)
  {
    /*
    for(unsigned int b=0;b<uncombined.size();b++)
    {
      if(bots[uncombined[b]].y()==9)
      {
        bots[uncombined[b]].move("down");
      }
      else if(bots[builders[b]].y()==10)
      {
        bots[builders[b]].move("down");
      }
    }
    */
    bots[uncombined[0]].combine(bots[uncombined[1]],bots[uncombined[2]],bots[uncombined[3]]);
  }
  // Handles all of the non builders
  for(unsigned int b=0;b<actors.size();b++)
  {
    Unit* target = findNearestTarget(bots[actors[b]]);
    moveTowardsTarget(bots[actors[b]], *target);
    if(inRange(bots[actors[b]], *target))
    {
      cout<<"In RANGE!"<<endl;
      unload(bots[actors[b]],*target);
    }
  }
  return true;
}
示例#16
0
//TODO Test if you can build something and act on it in one turn
void AI::buildQueue()
{
  for(unsigned int i=0;i<plants.size();i++)
  {
    //cout<<"Working on plant: "<<i<<endl;
    //cout<<"HP: "<<plants[i].health()<<endl;
    //if its my plant and it can do something
    if(plants[i].ownerID() == playerID() && plants[i].canAct())
    {
      //Spam talk
      string message="This is plant[" + plants[i].objectID();
      message+="] owned by Player: "+plants[i].ownerID();
      message+=" on turn "+turnNumber();
      //char * temp = message.c_str();
      plants[i].talk((char*)(message.c_str()));
      if(i==0)
      {
        plants[i].talk((char*)("Did calling talk twice append or replace the usual string?"));
      }
      //if you don't have a leaf
      if(!plants[i].leaf())
      {
        if(canDo(i,LEAF))
        {
          //a place to try growing a leaf
          space sp(plants[i].x(), plants[i].y(),i,LEAF);
          sp.rating=evalTree(leafTree,sp);
          que.push(sp);
        }
        /*
        else
        {
          space sp(plants[i].x(), plants[i].y(),i,LEAF);
          cout<<"CANT DO: ";
          sp.display();
        }
        */
      }
      //if you want to generate light
      else
      {
        //cout<<"Pushing NOOP"<<endl;
        space sp(plants[i].x(), plants[i].y(),i,NOOP);
        sp.rating=evalTree(noopTree,sp);
        //que.push(sp);
      }
      //if it doesn't have a root
      if(!plants[i].root())
      {
        //I can do a root
        if(canDo(i,ROOT))
        {
          //a place to try growing a root
          space sp(plants[i].x(), plants[i].y(),i,ROOT);
          sp.rating=evalTree(rootTree,sp);
          que.push(sp);
        }
        /*
        else
        {
          space sp(plants[i].x(), plants[i].y(),i,ROOT);
          cout<<"CANT DO: ";
          sp.display();        
        }
        */
      }
      //for expansion
      else
      {
        if(canDo(i,SPREAD))
        {
          for(unsigned int r=0;r<4;r++)
          {
            space sp(plants[i].x()+xoff[r], plants[i].y()+yoff[r],i,SPREAD);
            if(canSpawnHere[sp.x+1][sp.y+1])
            {
              sp.rating=evalTree(rootTree,sp);
              que.push(sp);
            }
          }
        }
      }
      //if it doesn't have a flower and can make one
      if(!plants[i].flower())
      {
        if(canDo(i,FLOWER))
        {
          //a place to try growing a flower
          space sp(plants[i].x(), plants[i].y(),i,FLOWER);
          sp.rating=evalTree(flowerTree,sp);
          que.push(sp);
        }
      }
      //if you have a flower and can spawn
      else
      {
        if(canDo(i,SPAWN))
        {
          for(unsigned int r=0;r<4;r++)
          {
            space sp(plants[i].x()+xoff[r], plants[i].y()+yoff[r],i,SPAWN);
            if(canSpawnHere[sp.x+1][sp.y+1])
            {
              sp.rating=evalTree(spawnTree,sp);
              que.push(sp);
            }
          }
        }
      }
    }
  }
 // //cout<<"Bot of Build QUE"<<endl;
}
double AI::DLMM(boardState* nodeOrig, int depth, int QS_Depth, bool maximizingPlayer, double alpha, double beta){
	bool terminal = false;
	double newAlpha = alpha;
	double newBeta = beta;
	double newVal = alpha;
	int moverid = playerID();
	map<string, int>::iterator it1;

	if (!maximizingPlayer){
		if (moverid == 0){ moverid = 1; }
		else{ moverid = 0; }
	}
	
	vector<fakePiece> blank;
	if (kingInCheckmate(nodeOrig, moverid)){
		double retVal = calcHeuristic(moverid, nodeOrig, blank);
		return (retVal);
	}

	else if ((depth == 0 && nodeOrig->QS_State == false) || (depth == 0 && QS_Depth == 0)){
		double retVal = calcHeuristic(moverid, nodeOrig, blank);
		return (retVal);
	}

	else if (maximizingPlayer){
		newBeta = beta;
		newAlpha = alpha;
		newVal = alpha;

		possibleMovesStruct* possibleMovesMax = new possibleMovesStruct;
		allPossibleMoves(nodeOrig, possibleMovesMax, moverid);

		if (possibleMovesMax->availiableMoves.size() > 0){			
			int size = possibleMovesMax->availiableMoves.size() - 1;
			for (int i = size; i >= 0; i--){				
				boardState* nodeNew = new boardState;
				*(nodeNew) = *(nodeOrig);
				
				int fileFrom = possibleMovesMax->availiableMoves.top().fileFrom;
				int rankFrom = possibleMovesMax->availiableMoves.top().rankFrom;
				int fileTo = possibleMovesMax->availiableMoves.top().fileTo;
				int rankTo = possibleMovesMax->availiableMoves.top().rankTo;
				
				nodeNew->unofficialMove(fileFrom, rankFrom, fileTo, rankTo, moverid, 0, 2);
				
				if (depth != 0){
					newVal = DLMM(nodeNew, depth, QS_Depth - 1, false, newAlpha, newBeta);
				}
				else{
					newVal = DLMM(nodeNew, depth - 1, QS_Depth, false, newAlpha, newBeta);
				}

				if (newVal <= newAlpha){ // Fail low
					
					possibleMovesMax->availiableMoves.pop();
				}
				else if (newVal >= newBeta){ //Fail high -> prune because fail high on max
					size = -1;
					it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
					while (possibleMovesMax->availiableMoves.size() > 0){
						possibleMovesMax->availiableMoves.pop();
					}
				}
				else{ // New best value/alpha
					newAlpha = newVal;
					it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
					possibleMovesMax->availiableMoves.pop();
				}
				delete nodeNew;
			}
			delete possibleMovesMax;

			//History table updates and inserts
			int currentCount = it1->second;
			string currentString = it1->first;
			myHistoryTable.erase(currentString);
			myHistoryTable[currentString] = currentCount + 1;
			return newAlpha;
		}
		else{  
			return alpha;
		}
	}
	else{ //Min player
		newAlpha = alpha;
		newBeta = beta;
		
		if (alpha != 0){
			newBeta = alpha;
		}
		else{
			newBeta = 1000;
		}
		newVal = 0;
		possibleMovesStruct* possibleMovesMax = new possibleMovesStruct;
		allPossibleMoves(nodeOrig, possibleMovesMax, moverid);
		
		if (possibleMovesMax->availiableMoves.size() > 0){
			
			int size = possibleMovesMax->availiableMoves.size() - 1;
			for (int i = size; i >= 0; i--){
				boardState* nodeNew = new boardState;
				*(nodeNew) = *(nodeOrig);
				
				int fileFrom = possibleMovesMax->availiableMoves.top().fileFrom;
				int rankFrom = possibleMovesMax->availiableMoves.top().rankFrom;
				int fileTo = possibleMovesMax->availiableMoves.top().fileTo;
				int rankTo = possibleMovesMax->availiableMoves.top().rankTo;
				
				nodeNew->unofficialMove(fileFrom, rankFrom, fileTo, rankTo, moverid, 0, 2);
				if (depth == 0){
					newVal = DLMM(nodeNew, depth, QS_Depth - 1, true, newAlpha, newBeta);
				}
				else{
					newVal = DLMM(nodeNew, depth - 1, QS_Depth, true, newAlpha, newBeta);
				}
				
				if (newVal <= newAlpha){ // Fail low on min -> prune
					size = -1;
					it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
					while (possibleMovesMax->availiableMoves.size() > 0){
						possibleMovesMax->availiableMoves.pop();
					}

				}
				else if (newVal >= newBeta){ //Fail high on min -> dont use this one
					
					possibleMovesMax->availiableMoves.pop();
				}
				else{ //We found a new value which is lower than the highest beta
					
					newBeta = newVal;
					it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
					possibleMovesMax->availiableMoves.pop();
				}
				delete nodeNew;
			}
			delete possibleMovesMax;

			//History table updates and inserts
			int currentCount = it1->second;
			string currentString = it1->first;
			myHistoryTable.erase(currentString);
			myHistoryTable[currentString] = currentCount + 1;

			return (newBeta);
		}
		else{
			return (beta);
		}
	}


}
void AI::IDDLMM(boardState* nodeOrig, int depth, int QS_Depth, bool maximizingPlayer, double a, double b){
	double bestVal = 0; //Tracks best heuristic values calculated yet
	int moverid = playerID(); //The player moving is us, so call playerID() to return our playerID
	int fileFromBest, rankFromBest, fileToBest, rankToBest; //The best moves to and from coordinates
	clock_t t; //Used to keep track offthe time we started at
	clock_t t2; // Used for tracking the duration of the current depth
	clock_t t3; 
	vector<double> time; //Holds the times it took for each level of depth we search in order to calculate future depths
	double estimatedTime;
	
	possibleMovesStruct* possibleMovesMax = new possibleMovesStruct;
	allPossibleMoves(nodeOrig, possibleMovesMax, moverid); //Stores all possible moves for the given boardstate into possibleMovesMax

	map<string, int>::iterator it1;
	t = clock(); //Time we start the algorithm
	
	if (possibleMovesMax->availiableMoves.size() > 0){
		for (int i = 1; i <= depth; i++){
			delete possibleMovesMax;
			possibleMovesMax = new possibleMovesStruct;
			allPossibleMoves(nodeOrig, possibleMovesMax, moverid);
			if (possibleMovesMax->availiableMoves.size() > 0){
				//Calculating time for this depth
				t2 = clock();
				for (int j = possibleMovesMax->availiableMoves.size() - 1; j >= 0; j--){
					double newVal;
					boardState* nodeNew = new boardState;
					
					*(nodeNew) = *(nodeOrig);
					
					int fileFrom = possibleMovesMax->availiableMoves.top().fileFrom;
					int rankFrom = possibleMovesMax->availiableMoves.top().rankFrom;
					int fileTo = possibleMovesMax->availiableMoves.top().fileTo;
					int rankTo = possibleMovesMax->availiableMoves.top().rankTo;

					if (!repeatedMovesLoss(fileFrom, rankFrom, fileTo, rankTo)){
						nodeNew->unofficialMove(fileFrom, rankFrom, fileTo, rankTo, moverid, 0, 2);
						newVal = DLMM(nodeNew, i - 1, QS_Depth, false, bestVal, b);
					}

					else{
						newVal = bestVal;
						possibleMovesMax->availiableMoves.pop();
					}
					if (newVal <= bestVal){
						possibleMovesMax->availiableMoves.pop();
						// Move on 
					}
					else{
						bestVal = newVal;
						it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
						fileFromBest = fileFrom;
						rankFromBest = rankFrom;
						fileToBest = fileTo;
						rankToBest = rankTo;
						possibleMovesMax->availiableMoves.pop();		
					}
					delete nodeNew;
					possibleMovesMax->availiableMoves.pop();
				}

				//History table updates and inserts
				int currentCount = it1->second;
				string currentString = it1->first;
				myHistoryTable.erase(currentString);
				myHistoryTable[currentString] = currentCount + 1;

				/*
				// Time Heuristic area
				*/
				
				//End time for this depth -> pushes it on the time vector
				t2 = clock() - t2;

				double tempTime = ((double)t2 / CLOCKS_PER_SEC); //Time in sec
				double estTimePerNode;
				
				time.push_back(tempTime);

				double estBranch;
				if (time.size() > 3){
					for (int n = time.size() - 1; n > 2; n--){
						//Adds up the factor difference between the times
						//i.e. 15 sec turn 1 45 sec turn 2 135 sec turn 3
						// => 0+ 135/45 = 3 + 45/15 = 6 
						estBranch += time[n] / time[n - 1];
					}

					// Dividing by the number of calculations done to get us an estimated branching factor
					estBranch = (estBranch / (time.size() - 3));
					
					for (int n = time.size() - 1; n >= 2; n--){
						//Estimates the time per node by taking the time for a specific level
						// and dividing it by the branching factor ^ branch level it was at
						estTimePerNode += time[n] / (pow(estBranch, n + 1));
					}

					//Divides by the number of calculations done / the size of the time array to get an average
					estTimePerNode = (estTimePerNode / (time.size() - 2));

					// Gets the estimated time for the next layer
					estimatedTime = (estTimePerNode)* pow(estBranch, i + 1);
					
					t3 = clock() - t;
					double timeSinceStart = ((double)t3 / CLOCKS_PER_SEC);

					//If we have spent more than x seconds on this move then quit where x is a scaling value from 1 to 5 based on time left
					double timeToSpend = 4 * (double)(((players[moverid].time()) / 900)) + 1;
					if (t3 >= timeToSpend){
						i = depth + 1;
					}
					//If making the next move is estimated to take longer than x seconds for this turn then quit and return 
					// where x is a scaling value from 1 to 5 based on time left
					else if (timeSinceStart + estimatedTime >= (timeToSpend + .5)){
						i = depth + 1;
					}
					estimatedTime = 0;
					estTimePerNode = 0;
					estBranch = 0;
				}
				else{ //Used for depths < 4
					// Estimates that the time will be the time it took for this round * the number of availiable moves
					// as we assume here the branching factor will be about the same
					
					estimatedTime = (tempTime * (possibleMovesMax->availiableMoves.size()));

					t3 = clock() - t;
					double timeSinceStart = ((double)t3 / CLOCKS_PER_SEC);
					double timeToSpend = 4 * (double)(players[moverid].time() / 900) + 1;

					//If we have spent more than x seconds on this move then quit where x is a scaling value from 1 to 5 based on time left
					if (timeSinceStart >= timeToSpend){
						i = depth + 1;
					}

					//If making the next move is estimated to take longer than x seconds for this turn then quit and return 
					// where x is a scaling value from 1 to 5 based on time left 
					else if (timeSinceStart + estimatedTime >= (timeToSpend + .5)){
						i = depth + 1;
					}
				}
			}

			for (int i = 0; i < pieces.size(); i++){
				//Make the move
				if (pieces[i].file() == fileFromBest && pieces[i].rank() == 9 - rankFromBest){
					pieces[i].move(fileToBest, 9 - rankToBest, int('Q'));
					i = pieces.size();
				}
			}
		}
	}
	else{
		//Error - do an illegal move and view log
		Piece piecetoMove;
		piecetoMove = pieces[0];
		piecetoMove.move(50, 50, int('Q'));
	}
	return;
}
示例#19
0
//This function is called each time it is your turn.
//Return true to end your turn, return false to ask the server for updated information.
bool AI::run()
{
  Fish* coolFish = getFish(0, 0, fishes);
  if(coolFish != NULL)
  {
    coolFish->carryingWeight();
  }
  for(int i = 0;i < tiles.size();i++)
  {
    if(tiles[i].owner() == playerID() &&
       getFish(tiles[i].x(), tiles[i].y(), fishes) == NULL)
    {
      for(int p = 0;p<species.size(); p++)
      {
        if(species[p].season() == currentSeason())
        {
          if(players[playerID()].spawnFood() >= species[p].cost() &&
             tiles[i].hasEgg() == false)
          {
            species[p].spawn(tiles[i].x(), tiles[i].y());
          }
        }
      }
    }
  }
  for(int i = 0;i < fishes.size();i++)
  {
    if(fishes[i].owner() == playerID())
    {
      int x = fishes[i].x();
      int y = fishes[i].y();
      if(fishes[i].x() >= 1)
      {
        if(getTile(x - 1, y, mapHeight(), tiles).trashAmount() > 0 &&
           fishes[i].carryingWeight() + 1 <= fishes[i].carryCap())
        {
          fishes[i].pickUp(x - 1, y, 1);
        }
      }
      if(fishes[i].carryingWeight() > 0)
      {
        if(fishes[i].x() < mapWidth()/2 - boundLength() - 1)
        {
          if(fishes[i].y() != 0)
          {
            if(getTile(x,y - 1,mapHeight(),tiles).owner() == 2 &&
               getFish(x,y + 1,fishes) == NULL)
            {
              fishes[i].drop(x, y - 1, fishes[i].carryingWeight());
            }
          }
          else
          {
            if(getTile(x,y + 1,mapHeight(),tiles).owner() == 2 &&
               getFish(x,y + 1,fishes) == NULL)
            {
              fishes[i].drop(x, y + 1, fishes[i].carryingWeight());
            }
          }
        }
      }
      if(fishes[i].x() >= 1)
      {
        if(getTile(x - 1,y,mapHeight(),tiles).owner() != enemyAI_ID &&
           getTile(x - 1,y,mapHeight(),tiles).trashAmount() == 0)
        {
          if(getFish(x - 1, y, fishes) == NULL &&
             getTile(x - 1, y, mapHeight(), tiles).hasEgg() == false)
          {
            fishes[i].move(x - 1,y);
          }
        }
      }
    }
  }
  return true;
}
示例#20
0
//This function is called each time it is your turn.
//Return true to end your turn, return false to ask the server for updated information.
bool AI::run()
{
  cout << "Turn " << turnNumber() << endl;

  // Future: tell the map to update itself (saving history)
  _map = Map(this);

  // Update convenience data structures.
  myBases.erase(myBases.begin(),myBases.end());
  for (vector<Base>::iterator base = bases.begin();
       base != bases.end();
       base++) {
    if ((*base).owner() == playerID()) myBases.push_back(*base);
  }
  myViruses.erase(myViruses.begin(),myViruses.end());
  for (vector<Virus>::iterator virus = viruses.begin();
       virus != viruses.end();
       virus++) {
    if ((*virus).owner() == playerID()) myViruses.push_back(*virus);
  }


  if (_config[string("preset")].compare(string("Coverage"))) {
    players[playerID()].talk((char*)"The General: 0.52 (Coverage)");
  } else {
    players[playerID()].talk((char*)"The General: 0.52 (2xLem,1Rand)");
  }


  // Let the General command the army.
  Commander_Washington.Command();

  // The Old Way
  // // virus coverage strategy
  // build_shells(this,map);

  // // fewest spawns
  // distribute_base_spawning(this,map);


  // // loop through all of the bases
  // for(int i=0;i<bases.size();i++)
  // {
  //   // check if you own that base
  //   if(bases[i].owner() == playerID())
  //   {
  //     // check to see if you have enough cycles to spawn a level 0 virus
  //     if(baseCost() <= players[playerID()].cycles())
  //     {
  //       // spawn a level 0 virus at that base
  //       bases[i].spawn(0);
  //     }
  //   }
  // }

  // // loop through all of the viruses
  // for(int i=0;i<viruses.size();i++)
  // {
  //   // if you own that virus
  //   if(viruses[i].owner() == playerID())
  //   {
  //     // if the tile you want to move to is NOT a wall
  //     if(getTileAtLocation(viruses[i].x()+1, viruses[i].y()).owner() != 3)
  //     {
  //       // move the virus
  //       viruses[i].move(viruses[i].x()+1, viruses[i].y());
  //     }
  //   }
  // }
 // End your turn
  return true;
}
示例#21
0
//This function is called each time it is your turn.
//Return true to end your turn, return false to ask the server for updated information.
bool AI::run()
{
  //Iterate through every creature
  for(int ii = 0; ii < creatures.size(); ii++)
  { 
	//if I own the creature
	if (creatures[ii].owner() == playerID())
	{
		/*
		roles
		0 = herbivore
		1 = carnivore
		2 = breeder
		*/
		int role;

		// if herbivorism > carnivorism and has not much energy
		if (creatures[ii].herbivorism() > creatures[ii].carnivorism())
		{
			if (creatures[ii].energy() < energyPerTurn() * 5)
			{
				// if the creature has enough energy to survive
				role = 2;
				// time to get kinky
			}
			else
			{
				// if the creature doesn't have much energy
				role = 0;
				// must get noms
			}
		}
		else if (creatures[ii].herbivorism() < creatures[ii].carnivorism())
		{
			if (creatures[ii].energy() < energyPerTurn() * 5)
			{
				// if the creature has enough energy to survive
				role = 2;
				// time to get kinky
			}
			else
			{
				// if the creature doesn't have much energy
				role = 1;
				// must get noms
			}
		}

		//if (role == 0)
		{
			int plantLeft = getPlantAtLocation(creatures[ii].x() + 1, creatures[ii].y());
			int plantTop = getPlantAtLocation(creatures[ii].x(), creatures[ii].y() - 1);
			int plantRight = getPlantAtLocation(creatures[ii].x() - 1, creatures[ii].y());
			int plantDown = getPlantAtLocation(creatures[ii].x(), creatures[ii].y() + 1);

			if (plantLeft == 1 && creatures[ii].energy() < (5 * energyPerTurn()) && creatures[ii].canEat() == 1)
			{
				creatures[ii].eat(creatures[ii].x() + 1, creatures[ii].y());
			}
			else if (plantTop == 1 && creatures[ii].energy() < (5 * energyPerTurn()) && creatures[ii].canEat() == 1)
			{
				creatures[ii].eat(creatures[ii].x(), creatures[ii].y() - 1);
			}
			else if (plantRight == 1 && creatures[ii].energy() < (5 * energyPerTurn()) && creatures[ii].canEat() == 1)
			{
				creatures[ii].eat(creatures[ii].x() - 1, creatures[ii].y());
			}
			else if (plantDown == 1 && creatures[ii].energy() < (5 * energyPerTurn()) && creatures[ii].canEat() == 1)
			{
				creatures[ii].eat(creatures[ii].x(), creatures[ii].y() + 1);
			}
			else
			{
				switch((rand() % 3) + 1)
				{
					case 0: // left
						creatures[ii].move(creatures[ii].x() + 2, creatures[ii].y());
						break;
					case 1: // up
						creatures[ii].move(creatures[ii].x(), creatures[ii].y() - 2);
						break;
					case 2: // right
						creatures[ii].move(creatures[ii].x() - 2, creatures[ii].y());
						break;
					case 3: // down
						creatures[ii].move(creatures[ii].x(), creatures[ii].y() + 2);
						break;
				}
			}
		}


		if (creatures[ii].movementLeft() > 2)
		{
			return false;
		}








		/*
	  //check if there is a plant to that creature's left
	  int plantIn = getPlantAtLocation(creatures[ii].x() + 1, creatures[ii].y());

	  //if there is no plant to my left, or there is a plant of size 0, and there is no creature to my left
	  if ((plantIn == -1 || (plantIn != 1 && plants[plantIn].size() == 0)) && getCreatureAtLocation(creatures[ii].x() + 1, creatures[ii].y()) == -1)
	  { 
		//if x is in the range of the map, and y is in the range of the map
		if(0 <= creatures[ii].x() + 1 && creatures[ii].x() + 1<mapWidth() && 0 <= creatures[ii].y() && creatures[ii].y() < mapHeight())
		{ 
			//if I have ennough health to move, and have movment left
			if (creatures[ii].currentHealth() > healthPerMove() && creatures[ii].movementLeft() > 0)
			{ 
				//move creature to the left by incrementing its x cooridinate, and not changing its y
				creatures[ii].move(creatures[ii].x() + 1,creatures[ii].y());
				
			}
		}
	  }      

	  //check if there is a plant to my left
	  plantIn = getPlantAtLocation(creatures[ii].x()+1,creatures[ii].y());*/

		/*
	  //check if there is a creature to my left
	  int creatIn = getCreatureAtLocation(creatures[ii].x()+1,creatures[ii].y());
	  //if there is a plant to my left, and its size is > 0, and this creature has not already eaten this turn
	  if (plantIn != -1 && plants[plantIn].size()>0 && creatures[ii].canEat()==1)
	  {
		//eat the plant, using its x and y
		creatures[ii].eat(plants[plantIn].x(),plants[plantIn].y());
	  }
	  //else if there is a creature to my left, and it is not my creature and this creature has not eaten yet
	  else if (creatIn!=-1 && creatures[creatIn].owner()!=playerID() && creatures[ii].canEat()==1)
	  { //take a bite out of this creature
		creatures[ii].eat(creatures[creatIn].x(),creatures[creatIn].y());
	  }
	  //else if there is a creature to my left, and it is my creature, and neither has bred this turn
	  else if (creatIn!=-1 && creatures[creatIn].owner()==playerID() && creatures[ii].canBreed()==1 && creatures[creatIn].canBreed()==1)
	  { //if both creatures have enough health to breed
		if (creatures[ii].currentHealth()>healthPerBreed() && creatures[creatIn].currentHealth()>healthPerBreed())
		{ //breed with this creature
		  creatures[ii].breed(creatures[creatIn]);
		}
	  }*/
	}
  }
  return true;
}
QTSS_Error LogRequest(QTSS_ClientSessionObject inClientSession,
	QTSS_RTSPSessionObject inRTSPSession, QTSS_CliSesClosingReason *inCloseReasonPtr)
{
	static StrPtrLen sUnknownStr(sVoidField);
	static StrPtrLen sTCPStr("TCP");
	static StrPtrLen sUDPStr("UDP");

	//Fetch the URL, user agent, movielength & movie bytes to log out of the RTP session
	enum {
		eTempLogItemSize = 256, // must be same or larger than others
		eURLSize = 256,
		eUserAgentSize = 256,
		ePlayerIDSize = 32,
		ePlayerVersionSize = 32,
		ePlayerLangSize = 32,
		ePlayerOSSize = 32,
		ePlayerOSVersSize = 32,
		ePlayerCPUSize = 32
	};

	char tempLogItemBuf[eTempLogItemSize] = { 0 };
	StrPtrLen tempLogStr(tempLogItemBuf, eTempLogItemSize - 1);

	//
	// Check to see if this session is closing because authorization failed. If that's
	// the case, we've logged that already, let's not log it twice

	UInt32 theLen = 0;
	UInt32* authorizationFailed = NULL;
	(void)QTSS_GetValuePtr(inClientSession, sLoggedAuthorizationAttrID, 0, (void**)&authorizationFailed, &theLen);
	if ((authorizationFailed != NULL) && (*authorizationFailed > 0))
		return QTSS_NoErr;

	///inClientSession should never be NULL
	//inRTSPRequest may be NULL if this is a timeout

	OSMutexLocker locker(sLogMutex);
	CheckAccessLogState(false);
	if (sAccessLog == NULL)
		return QTSS_NoErr;

	//if logging is on, then log the request... first construct a timestamp
	char theDateBuffer[QTSSRollingLog::kMaxDateBufferSizeInBytes];
	bool result = QTSSRollingLog::FormatDate(theDateBuffer, sLogTimeInGMT);


	//for now, just ignore the error.
	if (!result)
		theDateBuffer[0] = '\0';

	theLen = sizeof(QTSS_RTSPSessionObject);
	QTSS_RTSPSessionObject theRTSPSession = inRTSPSession;
	if (theRTSPSession == NULL)
		(void)QTSS_GetValue(inClientSession, qtssCliSesLastRTSPSession, 0, (void*)&theRTSPSession, &theLen);

	// Get lots of neat info to log from the various dictionaries

	// Each attribute must be copied out to ensure that it is NULL terminated.
	// To ensure NULL termination, just memset the buffers to 0, and make sure that
	// the last byte of each array is untouched.

	Float32* packetLossPercent = NULL;
	Float64* movieDuration = NULL;
	UInt64* movieSizeInBytes = NULL;
	UInt32* movieAverageBitRatePtr = 0;
	UInt32 clientPacketsReceived = 0;
	UInt32 clientPacketsLost = 0;
	StrPtrLen* theTransportType = &sUnknownStr;
	SInt64* theCreateTime = NULL;
	SInt64* thePlayTime = NULL;

	UInt32 startPlayTimeInSecs = 0;

	char localIPAddrBuf[20] = { 0 };
	StrPtrLen localIPAddr(localIPAddrBuf, 19);

	char localDNSBuf[70] = { 0 };
	StrPtrLen localDNS(localDNSBuf, 69);

	char remoteDNSBuf[70] = { 0 };
	StrPtrLen remoteDNS(remoteDNSBuf, 69);

	char remoteAddrBuf[20] = { 0 };
	StrPtrLen remoteAddr(remoteAddrBuf, 19);

	char playerIDBuf[ePlayerIDSize] = { 0 };
	StrPtrLen playerID(playerIDBuf, ePlayerIDSize - 1);

	// First, get networking info from the RTSP session
	(void)QTSS_GetValue(inClientSession, qtssCliRTSPSessLocalAddrStr, 0, localIPAddr.Ptr, &localIPAddr.Len);
	(void)QTSS_GetValue(inClientSession, qtssCliRTSPSessLocalDNS, 0, localDNS.Ptr, &localDNS.Len);
	(void)QTSS_GetValue(inClientSession, qtssCliSesHostName, 0, remoteDNS.Ptr, &remoteDNS.Len);
	(void)QTSS_GetValue(inClientSession, qtssCliRTSPSessRemoteAddrStr, 0, remoteAddr.Ptr, &remoteAddr.Len);
	(void)QTSS_GetValue(inClientSession, qtssCliRTSPSessRemoteAddrStr, 0, playerID.Ptr, &playerID.Len);

	UInt32* rtpBytesSent = NULL;
	UInt32* rtcpBytesRecv = NULL;
	UInt32* rtpPacketsSent = NULL;

	// Second, get networking info from the Client's session.
	// (Including the stats for incoming RTCP packets.)
	char urlBuf[eURLSize] = { 0 };
	StrPtrLen url(urlBuf, eURLSize - 1);
	(void)QTSS_GetValue(inClientSession, qtssCliSesPresentationURL, 0, url.Ptr, &url.Len);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesPacketLossPercent, 0, (void**)&packetLossPercent, &theLen);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesMovieDurationInSecs, 0, (void**)&movieDuration, &theLen);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesMovieSizeInBytes, 0, (void**)&movieSizeInBytes, &theLen);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesMovieAverageBitRate, 0, (void**)&movieAverageBitRatePtr, &theLen);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesCreateTimeInMsec, 0, (void**)&theCreateTime, &theLen);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesFirstPlayTimeInMsec, 0, (void**)&thePlayTime, &theLen);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesRTPBytesSent, 0, (void**)&rtpBytesSent, &theLen);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesRTPPacketsSent, 0, (void**)&rtpPacketsSent, &theLen);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliSesRTCPBytesRecv, 0, (void**)&rtcpBytesRecv, &theLen);

	if (theCreateTime != NULL && thePlayTime != NULL)
		startPlayTimeInSecs = (UInt32)(((*theCreateTime - *thePlayTime) / 1000) + 0.5);


	// We need a value of 'c-bytes' to report as a log entry. This is supposed to be the total number
	// of bytes the client has received during the session. Unfortunately, the QT client does not give
	// us this number. We will use the following heuristic formula to estimate the number of bytes the
	// client has received during the session:
	//
	//     client-bytes-received = bytes-sent * (100.0 - percent-packet-lost) / 100.0
	//
	// The 'percent-packet-lost' value has been calculated internally by QTSS based on the RTCP packets
	// sent to the server from the client. If those values are accurate then the above formula will not 
	// be exactly correct but it will be nearly correct.

	UInt32 clientBytesRecv = (UInt32)((*rtpBytesSent * (100.0 - *packetLossPercent)) / 100.0);

	tempLogStr.Ptr[0] = 0; tempLogStr.Len = eUserAgentSize;
	(void)QTSS_GetValue(inClientSession, qtssCliSesFirstUserAgent, 0, tempLogStr.Ptr, &tempLogStr.Len);

	char userAgentBuf[eUserAgentSize] = { 0 };
	StrPtrLen userAgent(userAgentBuf, eUserAgentSize - 1);
	ReplaceSpaces(&tempLogStr, &userAgent, "%20");

	UserAgentParser userAgentParser(&userAgent);

	//  StrPtrLen* playerID = userAgentParser.GetUserID() ;
	StrPtrLen* playerVersion = userAgentParser.GetUserVersion();
	StrPtrLen* playerLang = userAgentParser.GetUserLanguage();
	StrPtrLen* playerOS = userAgentParser.GetrUserOS();
	StrPtrLen* playerOSVers = userAgentParser.GetUserOSVersion();
	StrPtrLen* playerCPU = userAgentParser.GetUserCPU();

	//  char playerIDBuf[ePlayerIDSize] = {};   
	char playerVersionBuf[ePlayerVersionSize] = { 0 };
	char playerLangBuf[ePlayerLangSize] = { 0 };
	char playerOSBuf[ePlayerOSSize] = { 0 };
	char playerOSVersBuf[ePlayerOSVersSize] = { 0 };
	char playerCPUBuf[ePlayerCPUSize] = { 0 };

	UInt32 size;
	//  (ePlayerIDSize < playerID->Len ) ? size = ePlayerIDSize -1 : size = playerID->Len;
	//  if (playerID->Ptr != NULL) memcpy (playerIDBuf, playerID->Ptr, size);

	(ePlayerVersionSize < playerVersion->Len) ? size = ePlayerVersionSize - 1 : size = playerVersion->Len;
	if (playerVersion->Ptr != NULL) memcpy(playerVersionBuf, playerVersion->Ptr, size);

	(ePlayerLangSize < playerLang->Len) ? size = ePlayerLangSize - 1 : size = playerLang->Len;
	if (playerLang->Ptr != NULL) memcpy(playerLangBuf, playerLang->Ptr, size);

	(ePlayerOSSize < playerOS->Len) ? size = ePlayerOSSize - 1 : size = playerOS->Len;
	if (playerOS->Ptr != NULL)  memcpy(playerOSBuf, playerOS->Ptr, size);

	(ePlayerOSVersSize < playerOSVers->Len) ? size = ePlayerOSVersSize - 1 : size = playerOSVers->Len;
	if (playerOSVers->Ptr != NULL) memcpy(playerOSVersBuf, playerOSVers->Ptr, size);

	(ePlayerCPUSize < playerCPU->Len) ? size = ePlayerCPUSize - 1 : size = playerCPU->Len;
	if (playerCPU->Ptr != NULL) memcpy(playerCPUBuf, playerCPU->Ptr, size);


	// clientPacketsReceived, clientPacketsLost, videoPayloadName and audioPayloadName
	// are all stored on a per-stream basis, so let's iterate through all the streams,
	// finding this information

	char videoPayloadNameBuf[32] = { 0 };
	StrPtrLen videoPayloadName(videoPayloadNameBuf, 31);

	char audioPayloadNameBuf[32] = { 0 };
	StrPtrLen audioPayloadName(audioPayloadNameBuf, 31);

	UInt32 qualityLevel = 0;
	UInt32 clientBufferTime = 0;
	UInt32 theStreamIndex = 0;
	bool* isTCPPtr = NULL;
	QTSS_RTPStreamObject theRTPStreamObject = NULL;

	for (UInt32 theStreamObjectLen = sizeof(theRTPStreamObject);
		QTSS_GetValue(inClientSession, qtssCliSesStreamObjects, theStreamIndex, (void*)&theRTPStreamObject, &theStreamObjectLen) == QTSS_NoErr;
		theStreamIndex++, theStreamObjectLen = sizeof(theRTPStreamObject))
	{

		UInt32* streamPacketsReceived = NULL;
		UInt32* streamPacketsLost = NULL;
		(void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrTotPacketsRecv, 0, (void**)&streamPacketsReceived, &theLen);
		(void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrTotalLostPackets, 0, (void**)&streamPacketsLost, &theLen);

		// Add up packets received and packets lost to come up with a session wide total
		if (streamPacketsReceived != NULL)
			clientPacketsReceived += *streamPacketsReceived;
		if (streamPacketsLost != NULL)
			clientPacketsLost += *streamPacketsLost;

		// Identify the video and audio codec types
		QTSS_RTPPayloadType* thePayloadType = NULL;
		(void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrPayloadType, 0, (void**)&thePayloadType, &theLen);
		if (thePayloadType != NULL)
		{
			if (*thePayloadType == qtssVideoPayloadType)
				(void)QTSS_GetValue(theRTPStreamObject, qtssRTPStrPayloadName, 0, videoPayloadName.Ptr, &videoPayloadName.Len);
			else if (*thePayloadType == qtssAudioPayloadType)
				(void)QTSS_GetValue(theRTPStreamObject, qtssRTPStrPayloadName, 0, audioPayloadName.Ptr, &audioPayloadName.Len);
		}

		// If any one of the streams is being delivered over UDP instead of TCP,
		// report in the log that the transport type for this session was UDP.
		if (isTCPPtr == NULL)
		{
			(void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrIsTCP, 0, (void**)&isTCPPtr, &theLen);
			if (isTCPPtr != NULL)
			{
				if (*isTCPPtr == false)
					theTransportType = &sUDPStr;
				else
					theTransportType = &sTCPStr;
			}
		}

		Float32* clientBufferTimePtr = NULL;
		(void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrBufferDelayInSecs, 0, (void**)&clientBufferTimePtr, &theLen);
		if ((clientBufferTimePtr != NULL) && (*clientBufferTimePtr != 0))
		{
			if (*clientBufferTimePtr > clientBufferTime)
				clientBufferTime = (UInt32)(*clientBufferTimePtr + .5); // round up to full seconds
		}

	}

	// Add the client buffer time to our client start latency (in whole seconds).
	startPlayTimeInSecs += clientBufferTime;

	if (*rtpPacketsSent == 0) // no packets sent
		qualityLevel = 0; // no quality
	else
	{
		if ((clientPacketsReceived == 0) && (clientPacketsLost == 0)) // no info from client 
			qualityLevel = 100; //so assume 100
		else
		{
			float qualityPercent = (float)clientPacketsReceived / (float)(clientPacketsReceived + clientPacketsLost);
			qualityPercent += (float).005; // round up
			qualityLevel = (UInt32)((float) 100.0 * qualityPercent); // average of sum of packet counts for all streams
		}
	}

	//we may not have an RTSP request. Assume that the status code is 504 timeout, if there is an RTSP
	//request, though, we can find out what the real status code of the response is
	static UInt32 sTimeoutCode = 504;
	UInt32* theStatusCode = &sTimeoutCode;
	theLen = sizeof(UInt32);
	(void)QTSS_GetValuePtr(inClientSession, qtssCliRTSPReqRealStatusCode, 0, (void **)&theStatusCode, &theLen);
	//  qtss_printf("qtssCliRTSPReqRealStatusCode = %"   _U32BITARG_   " \n", *theStatusCode);


	if (inCloseReasonPtr) do
	{
		if (*theStatusCode < 300) // it was a succesful RTSP request but...
		{
			if (*inCloseReasonPtr == qtssCliSesCloseTimeout) // there was a timeout
			{
				*theStatusCode = sTimeoutCode;
				//                  qtss_printf(" log timeout ");
				break;
			}

			if (*inCloseReasonPtr == qtssCliSesCloseClientTeardown) // there was a teardown
			{

				static QTSS_CliSesClosingReason sReason = qtssCliSesCloseClientTeardown;
				QTSS_CliSesClosingReason* theReasonPtr = &sReason;
				theLen = sizeof(QTSS_CliSesTeardownReason);
				(void)QTSS_GetValuePtr(inClientSession, qtssCliTeardownReason, 0, (void **)&theReasonPtr, &theLen);
				//              qtss_printf("qtssCliTeardownReason = %"   _U32BITARG_   " \n", *theReasonPtr);

				if (*theReasonPtr == qtssCliSesTearDownClientRequest) //  the client asked for a tear down
				{
					//                  qtss_printf(" client requests teardown  ");
					break;
				}

				if (*theReasonPtr == qtssCliSesTearDownUnsupportedMedia) //  An error occured while streaming the file.
				{
					*theStatusCode = 415;
					//                      qtss_printf(" log UnsupportedMedia ");
					break;
				}
				if (*theReasonPtr == qtssCliSesTearDownBroadcastEnded) //  a broadcaster stopped broadcasting
				{
					*theStatusCode = 452;
					//                      qtss_printf(" log broadcast removed ");
					break;
				}

				*theStatusCode = 500; // some unknown reason for cancelling the connection
			}

			//          qtss_printf("return status ");
						// just use the qtssCliRTSPReqRealStatusCode for the reason
		}

	} while (false);

	//  qtss_printf(" = %"   _U32BITARG_   " \n", *theStatusCode);


		// Find out what time it is
	SInt64 curTime = QTSS_Milliseconds();

	UInt32 numCurClients = 0;
	theLen = sizeof(numCurClients);
	(void)QTSS_GetValue(sServer, qtssRTPSvrCurConn, 0, &numCurClients, &theLen);

	/*
		IMPORTANT!!!!

		Some values such as cpu, #conns, need to be grabbed as the session starts, not when the teardown happened (I think)

	*/

#if TESTUNIXTIME
	char thetestDateBuffer[QTSSRollingLog::kMaxDateBufferSizeInBytes];
	TestUnixTime(QTSS_MilliSecsTo1970Secs(*theCreateTime), thetestDateBuffer);
	qtss_printf("%s\n", thetestDateBuffer);
#endif

	float zeroFloat = 0;
	UInt64 zeroUInt64 = 0;
	Float32 fcpuUtilized = 0;

	theLen = sizeof(fcpuUtilized);
	(void)QTSS_GetValue(sServer, qtssSvrCPULoadPercent, 0, &fcpuUtilized, &theLen);
	UInt32 cpuUtilized = (UInt32)fcpuUtilized;

	char lastUserName[eTempLogItemSize] = { 0 };
	StrPtrLen lastUserNameStr(lastUserName, eTempLogItemSize);

	char lastURLRealm[eTempLogItemSize] = { 0 };
	StrPtrLen lastURLRealmStr(lastURLRealm, eTempLogItemSize);

	//qtss_printf("logging of saved params are in dictionary \n");

	tempLogStr.Ptr[0] = 0; tempLogStr.Len = eTempLogItemSize;
	(void)QTSS_GetValue(inClientSession, qtssCliRTSPSesUserName, 0, tempLogStr.Ptr, &tempLogStr.Len);
	ReplaceSpaces(&tempLogStr, &lastUserNameStr, "%20");
	//qtss_printf("qtssRTSPSesLastUserName dictionary item = %s len = %" _S32BITARG_ "\n",lastUserNameStr.Ptr,lastUserNameStr.Len);

	tempLogStr.Ptr[0] = 0; tempLogStr.Len = eTempLogItemSize;
	(void)QTSS_GetValue(inClientSession, qtssCliRTSPSesURLRealm, 0, tempLogStr.Ptr, &tempLogStr.Len);
	ReplaceSpaces(&tempLogStr, &lastURLRealmStr, "%20");
	//qtss_printf("qtssRTSPSesLastURLRealm dictionary  item = %s len = %" _S32BITARG_ "\n",lastURLRealmStr.Ptr,lastURLRealmStr.Len);  

	char respMsgBuffer[1024] = { 0 };
	StrPtrLen theRespMsg;
	(void)QTSS_GetValuePtr(inClientSession, qtssCliRTSPReqRespMsg, 0, (void**)&theRespMsg.Ptr, &theRespMsg.Len);
	StrPtrLen respMsgEncoded(respMsgBuffer, 1024 - 1);
	SInt32 theErr = StringTranslator::EncodeURL(theRespMsg.Ptr, theRespMsg.Len, respMsgEncoded.Ptr, respMsgEncoded.Len);
	if (theErr <= 0)
		respMsgEncoded.Ptr[0] = '\0';
	else
	{
		respMsgEncoded.Len = theErr;
		respMsgEncoded.Ptr[respMsgEncoded.Len] = '\0';
	}

	//cs-uri-query
	char urlQryBuf[eURLSize] = { 0 };
	StrPtrLen urlQry(urlQryBuf, eURLSize - 1);
	(void)QTSS_GetValue(inClientSession, qtssCliSesReqQueryString, 0, urlQry.Ptr, &urlQry.Len);

	char tempLogBuffer[1024];
	char logBuffer[2048];
	// compatible fields (no respMsgEncoded field)
	::memset(logBuffer, 0, 2048);
	qtss_sprintf(tempLogBuffer, "%s ", (remoteAddr.Ptr[0] == '\0') ? sVoidField : remoteAddr.Ptr); //c-ip*
	::strcpy(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (theDateBuffer[0] == '\0') ? sVoidField : theDateBuffer);   //date* time*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (remoteDNS.Ptr[0] == '\0') ? sVoidField : remoteDNS.Ptr); //c-dns
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (url.Ptr[0] == '\0') ? sVoidField : url.Ptr);   //cs-uri-stem*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", startPlayTimeInSecs);  //c-starttime 
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", theCreateTime == NULL ? (UInt32)0 : (UInt32)(QTSS_MilliSecsTo1970Secs(curTime)
		- QTSS_MilliSecsTo1970Secs(*theCreateTime)));   //x-duration* 
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%" _S32BITARG_ " ", (UInt32)1);  //c-rate
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%" _S32BITARG_ " ", *theStatusCode);   //c-status*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (playerIDBuf[0] == '\0') ? sVoidField : playerIDBuf);   //c-playerid*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (playerVersionBuf[0] == '\0') ? sVoidField : playerVersionBuf); //c-playerversion
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (playerLangBuf[0] == '\0') ? sVoidField : playerLangBuf);   //c-playerlanguage*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (userAgent.Ptr[0] == '\0') ? sVoidField : userAgent.Ptr);   //cs(User-Agent) 
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (playerOSBuf[0] == '\0') ? sVoidField : playerOSBuf);   //c-os*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (playerOSVersBuf[0] == '\0') ? sVoidField : playerOSVersBuf);   //c-osversion
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (playerCPUBuf[0] == '\0') ? sVoidField : playerCPUBuf); //c-cpu*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%0.0f ", movieDuration == NULL ? zeroFloat : *movieDuration); //filelength in secs*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%" _64BITARG_ "d ", movieSizeInBytes == NULL ? zeroUInt64 : *movieSizeInBytes); //filesize in bytes*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", movieAverageBitRatePtr == NULL ? (UInt32)0 : *movieAverageBitRatePtr);    //avgbandwidth in bits per second
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", "RTP"); //protocol
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (theTransportType->Ptr[0] == '\0') ? sVoidField : theTransportType->Ptr);   //transport
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (audioPayloadName.Ptr[0] == '\0') ? sVoidField : audioPayloadName.Ptr); //audiocodec*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (videoPayloadName.Ptr[0] == '\0') ? sVoidField : videoPayloadName.Ptr); //videocodec*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", rtpBytesSent == NULL ? (UInt32)0 : *rtpBytesSent);    //sc-bytes*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", rtcpBytesRecv == NULL ? (UInt32)0 : *rtcpBytesRecv);    //cs-bytes*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", clientBytesRecv);  //c-bytes
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", rtpPacketsSent == NULL ? (UInt32)0 : *rtpPacketsSent);   //s-pkts-sent*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", clientPacketsReceived);    //c-pkts-recieved
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", clientPacketsLost);    //c-pkts-lost-client*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", (UInt32)1);  //c-buffercount 
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", clientBufferTime);     //c-totalbuffertime*
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", qualityLevel); //c-quality 
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (localIPAddr.Ptr[0] == '\0') ? sVoidField : localIPAddr.Ptr);   //s-ip 
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (localDNS.Ptr[0] == '\0') ? sVoidField : localDNS.Ptr); //s-dns
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", numCurClients);    //s-totalclients
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%"   _U32BITARG_   " ", cpuUtilized);  //s-cpu-util
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (urlQry.Ptr[0] == '\0') ? sVoidField : urlQry.Ptr); //cs-uri-query
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (lastUserName[0] == '\0') ? sVoidField : lastUserName); //c-username
	::strcat(logBuffer, tempLogBuffer);
	qtss_sprintf(tempLogBuffer, "%s ", (lastURLRealm[0] == '\0') ? sVoidField : lastURLRealm); //sc(Realm)
	::strcat(logBuffer, tempLogBuffer);

	::strcat(logBuffer, "\n");

	Assert(::strlen(logBuffer) < 2048);

	//finally, write the log message
	sAccessLog->WriteToLog(logBuffer, kAllowLogToRoll);

	return QTSS_NoErr;
}
示例#23
0
文件: game.cpp 项目: wheein/MiHaJong
int TableProtoScene::ScoreBoard::getScoreSign() {
	for (int i = DigitGroups - 1; i >= 0; --i)
		if (GameStatus::gameStat()->Player[playerID()].PlayerScore.digitGroup[i] > 0) return 1;
		else if (GameStatus::gameStat()->Player[playerID()].PlayerScore.digitGroup[i] < 0) return -1;
	return 0;
}
示例#24
0
//This function is called each time it is your turn.
//Return true to end your turn, return false to ask the server for updated information.
bool AI::run()
{
  //loop through all of the tiles
  for(int i = 0;i < tiles.size();i++)
  {
    //if this tile is one of my coves and does not have a fish on it
    if(tiles[i].owner() == playerID() &&
       getFishIndex(tiles[i].x(), tiles[i].y()) == -1)
    {
       if(getSpecies(SEA_STAR).spawn(tiles[i].x(),tiles[i].y()))
          std::cout<<"I am fish"<<std::endl;
       /*
      //loop through all of the species
      for(int p = 0;p<species.size(); p++)
      {
        //if the current species is in season
        if(species[p].season() == currentSeason())
        {
          //if I have enough food to spawn the fish in and there is not
          //an egg on that tile already
          if(players[playerID()].spawnFood() >= species[p].cost() &&
             tiles[i].hasEgg() == false)
          {
            //spawn the fish on that tile
            species[p].spawn(tiles[i].x(), tiles[i].y());
          }
        }
      }*/
    }
  }

  //loop through all of the fish
  for(int i = 0;i < fishes.size();i++)
  {
    //if this is my fish
    if(fishes[i].owner() == playerID())
    {
      int x = fishes[i].x();
      int y = fishes[i].y();
      if(fishes[i].x() >= 1)
      {
        //if the tile to the left has trash and the current fish can
        //carry at least one more trash
        if(getTile(x - 1, y).trashAmount() > 0 &&
           fishes[i].carryingWeight() + 1 <= fishes[i].carryCap())
        {
          //if the fish has enought health to pick up trash
          if(1 * trashDamage() < fishes[i].currentHealth())
          {
            //pick up trash to the left of the fish
            fishes[i].pickUp(x - 1, y, 1);
          }
        }
      }
      //if the fish carrying any trash
      if(fishes[i].carryingWeight() > 0)
      {
        //if the fish in the enemy's side
        if((fishes[i].x() < mapWidth()/2 - boundLength() - 1 && enemyAI_ID == 0) ||
           (fishes[i].x() > mapWidth()/2 + boundLength() + 1 && enemyAI_ID == 1))
        {
          if(fishes[i].y() != 0)
          {
            //if the tile above the fish is not a cove and has no fish
            if(getTile(x, y - 1).owner() == 2 && getFishIndex(x, y + 1) == -1)
            {
              //drop all of the trash the fish is carrying
              fishes[i].drop(x, y - 1, fishes[i].carryingWeight());
            }
          }
          else if(fishes[i].y() != mapHeight() - 1)
          {
            //if the tile below the fish is not a cove and has no fish
            if(getTile(x,y + 1).owner() == 2 && getFishIndex(x,y + 1) == -1)
            {
              //drop all of the trash the fish is carrying
              fishes[i].drop(x, y + 1, fishes[i].carryingWeight());
            }
          }
        }
      }
      if(fishes[i].x() >= 1)
      {
        //if the tile to the left is not an enemy cove and there is no trash
        if(getTile(x - 1,y).owner() != enemyAI_ID &&
           getTile(x - 1,y).trashAmount() == 0)
        {
          //if the tile to the left does not have a fish and does not have an
          //egg
          if(getFishIndex(x - 1, y) == -1 &&
             getTile(x - 1, y).hasEgg() == false)
          {
            //move to the left
            fishes[i].move(x - 1, y);
          }
        }
        //get the fish to the left
        int target = getFishIndex(x - 1, y);
        //if there is a fish to the left and the fish has attacks left
        if(target != -1 && fishes[i].attacksLeft() > 0)
        {
          //if the fish is not a cleaner shrimp
          if(fishes[i].species() != CLEANER_SHRIMP)
          {
            //if the fish to the left is an enemy fish
            if(fishes[target].owner() == enemyAI_ID)
            {
               //attack the fish
               fishes[i].attack(fishes[target]);
            }
          }
          else
          {
             //this is if the fish is a cleaner shrimp

             //if the fish to the left is a friendly fish
             if(fishes[target].owner() != enemyAI_ID)
             {
                //heal the fish
                fishes[i].attack(fishes[target]);
             }
          }
        }
      }
    }
  }
  return true;
}