Ejemplo n.º 1
0
Archivo: game.cpp Proyecto: Tarrke/tbtd
void Game::levelDesign()
{
  // For the moment this function is fully automated
  // maybe in the future i'll need to add some features for level
  // desiners
  int num_mobs = 3;
  int num_towers = 5;
  
  grille->generatePath();
  grille->print();
  
  for( int i = 0; i < num_mobs; ++i )
  {
    Mob * nouvMob = new Mob(100,4,grille->getPath());
    
    mobs.push_back(nouvMob);
  }
  
  for( int i = 0; i < num_towers; ++i )
  {
    Tower * nouvTower = new Tower(1, 2, 50, 1, 10, 35+i, grille->getSize());
    gold_ -= nouvTower->howMuch();
    towers.push_back(nouvTower);
  }
}
Ejemplo n.º 2
0
Game::Game(): QGraphicsView(){
    // create a scene
    scene = new QGraphicsScene(this);
    scene->setSceneRect(0,0,800,600);

    // set the scene
    setScene(scene);

    // create a tower
    Tower * t = new Tower();
    t->setPos(250,250);

    // add the tower to scene
    scene->addItem(t);

    // set curosr
    cursor = nullptr;
    build = nullptr;
    setMouseTracking(true);

    // alter window
    setFixedSize(800,600);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    // create enemy
    Enemy * enemy = new Enemy();
    scene->addItem(enemy);

    // test code
    BuildTowerIcon * ic = new BuildTowerIcon();
    scene->addItem(ic);

}
Ejemplo n.º 3
0
int main() {
	Tower tower = Tower();
	tower.display();

	system("Pause");
	return 0;
}
Ejemplo n.º 4
0
void MultiplayerMap::UpdateEnemyPathing()
{
	for (int i = 0; i < towers.size(); i++)
	{
		Tower *t = towers.at(i);
		int x = t->GetX() / 32;
		int y = t->GetY() / 32;

		pathingArr[TILES_X * y + x].type = 1;
		pathingArr[TILES_X * (y + 1) + x].type = 1;
		pathingArr[TILES_X * y + (x + 1)].type = 1;
		pathingArr[TILES_X * (y + 1) + (x + 1)].type = 1;
	}

	for (int i = 0; i < enemies.size(); i++)
	{
		Enemy *en = enemies.at(i);
		Vector2f pos = en->GetPos();
		TileNode enemyPos = TileNode(pos.x / 32, pos.y / 32, nullptr);

		TileNode destination;
		if (en->GetOwnerID() == 1)
		{
			destination = endNode;
		}
		else
			destination = startNode;

		vector<TileNode> enemyPath = pathfinder->Search(enemyPos, destination);

		enemyPath.insert(enemyPath.begin(), enemyPos);
		en->UpdatePath(enemyPath);
	}
}
Ejemplo n.º 5
0
//-----------------------------------------------------------------------------
// create vertex and index buffers
void Wreck::createBuffers()
{
  int sideSteps = 50;
  int outSteps = 240;

  int ringSteps = 30;
  int circleSteps = 50;

  int vertexCount = 3* (outSteps+1) * (sideSteps+1);
  int indexCount = 3*6*outSteps*sideSteps;

  vertexCount += 3* (circleSteps+1) * (ringSteps+1);
  indexCount += 3*6*circleSteps*ringSteps;

  m_vertexes = mgVertexTA::newBuffer(vertexCount);
  m_indexes = mgDisplay->newIndexBuffer(indexCount, false, true);

  for (int i = 0; i < 3; i++)
  {
    mgMatrix4 model;
    model.translate(0, 0, 65+40*i);
    createRing(model, ringSteps, circleSteps);
  }

  createSpine(sideSteps, outSteps);

  for (int i = 0; i < m_towers.length(); i++)
  {
    Tower* tower = (Tower*) m_towers[i];
    if (tower != NULL)
      tower->createBuffers();
  }
}
Ejemplo n.º 6
0
void GeneticAlgorithmProfile1::RestoreState(cocos2d::Layer& _sc)
{
    GameScene* gs = (GameScene*) & _sc;
    ///////////////////////////////////////////////////////
    //restore the gamestate
    gs->gameState = this->gamestateBK;
    gs->playerHandler->SetCurrency(this->currencyBK);
    gs->playerHandler->SetLifePoints(this->lifePointsBK);
    gs->playerHandler->SetPlayerName(this->playerNameBK);
    gs->creepDeploymentDelay = this->creepSpawnDelayBK;
    gs->nextWaveStartingDelay = this->nextWaveStartingDelayBK;
    ///////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////
    //restore the wave state
    this->speedMultiplier = this->speedMultiplierBK;
    this->hpMultiplier = this->hpMultiplierBK;
    this->numOfStartingCreeps = this->numOfStartingCreepsBK;
    this->numOfCreepsMultiplier = this->numOfCreepsMultiplierBK;
    this->numOfCreepsAddedPerWave = this->numOfCreepsAddedPerWaveBK;
    this->specialCreepSet = this->specialCreepSetBK;
    this->specialCreepSpeedMultiplier = this->specialCreepSpeedMultiplierBK;
    this->specialCreepHPMultiplier = this->specialCreepHPMultiplierBK;
    this->specialCreepSpawnFrequency = this->specialCreepSpawnFrequencyBK;
    this->roundsAfterSpawn = this->roundsAfterSpawnBK;
    this->multiplyCreepNumbersPerRound = this->multiplyCreepNumbersPerRoundBK;
    this->round = this->roundBK;
    ///////////////////////////////////////////////////////
    //remove speed boost of tower
    for ( std::list<Tower*>::iterator tower = gs->towerslist.begin(); tower != gs->towerslist.end(); ++tower )
    {
        Tower* t = *tower;
        t->SetInbetweenAttacksPeriod(t->GetInbetweenAttacksPeriod() * speedBoost);
    }
}
void MultiBullet::nextFrame(){
    Tower *temp = getTower();
    if(temp != NULL){
        SetPosition(temp->GetPosition().x, temp->GetPosition().y);
        m_circ = sf::Shape::Circle(temp->GetPosition().x, temp->GetPosition().y, m_attack_radius, sf::Color::Red, 2, sf::Color::Blue);
    }

}
Ejemplo n.º 8
0
double tower_height(const Tower& t){
  Tower::const_iterator it;
  double res = 0;
  for(it=t.begin(); it!=t.end(); it++){
    res += it->height();
  }    
  return res;
}
Ejemplo n.º 9
0
void Enemy::getRemoved()
{
	CCObject *pObject = NULL;
	CCARRAY_FOREACH(attackedBy, pObject)
	{
		Tower *attacker = (Tower*)pObject;
		attacker->targetKilled();
	}
Ejemplo n.º 10
0
Tower *Tower::create(TowerType type, ControllerType controller) {
    Tower *tower = new Tower();
    if (tower && tower->initWithType(type, controller)) {
        tower->autorelease();
        return tower;
    }
    CC_SAFE_DELETE(tower);
    return tower;
}
Ejemplo n.º 11
0
void printJet(Jet *jet)
{

  GenParticle *particle;
  Muon *muon;

  Track *track;
  Tower *tower;

  TObject *object;
  TLorentzVector momentum;
      momentum.SetPxPyPzE(0.0, 0.0, 0.0, 0.0);
      //TRefArray constituentarray(jet->Constituents);
      TRefArray particlearray(jet->Particles);
      cout<<"Looping over jet constituents. Jet pt: "<<jet->PT<<", eta: "<<jet->Eta<<", phi: "<<jet->Phi<<endl;      

      // Loop over all jet's constituents
      for(Int_t j = 0; j < jet->Constituents.GetEntriesFast(); ++j)
      {
        object = jet->Constituents.At(j);
        // Check if the constituent is accessible
        if(object == 0) continue;

        if(object->IsA() == GenParticle::Class())
        {
          particle = (GenParticle*) object;
          cout << "    GenPart pt: " << particle->PT << ", eta: " << particle->Eta << ", phi: " << particle->Phi << endl;
          momentum += particle->P4();
        }
        else if(object->IsA() == Track::Class())
        {
          track = (Track*) object;
          cout << "    Track pt: " << track->PT << ", eta: " << track->Eta << ", phi: " << track->Phi << endl;
          momentum += track->P4();
        }
        else if(object->IsA() == Tower::Class())
        {
          tower = (Tower*) object;
          cout << "    Tower pt: " << tower->ET << ", eta: " << tower->Eta << ", phi: " << tower->Phi << endl;
          momentum += tower->P4();
        }
        else if(object->IsA() == Muon::Class())
        {
          muon = (Muon*) object;
          cout << "    Muon pt: " << muon->PT << ", eta: " << muon->Eta << ", phi: " << muon->Phi << endl;
          momentum += muon->P4();
        }
      }
      cout << " constituent sum pt:  " << momentum.Pt() <<" eta "<< momentum.Eta()  <<"  phi " << momentum.Phi() << std::endl;


      for (Int_t j =0; j<jet->Particles.GetEntries();  j++){
     		GenParticle *p_tmp = (GenParticle*) particlearray.At(j);
		printGenParticle(p_tmp);
	}
}
Ejemplo n.º 12
0
Float FireTower(Script * script)
{
	Tower * tower = (Tower *)script->GetSource();
	if ((tower != NULL) && (tower->GetState() == true) && (tower->CheckType(OBJ_TYPE_TOWER) == true))
	{
		AddProjectile(tower);
		return true;
	}
	return false;
}
Ejemplo n.º 13
0
void Game::build_mode_run() {

	draw_all_views();

	if( keyboard.isKeyPressed() ) {
		coord xy = gs->cursor->get_coord();       //get current location of cursor
    coord oldxy = xy;
		switch( keyboard.getKeyPressed() ) {	
		case 'K':         //left arrow
			if( xy.x > 0 ) {
				xy.x = xy.x - 1;
				update_cursor( xy, oldxy );
				m_change = true;
			}
			break;
		case 'M':         //right arrow
			if( xy.x < 14 ) {
				xy.x = xy.x + 1;
				update_cursor( xy, oldxy );
				m_change = true;
			}
			break;
		case 'H':         //up arrow
			if( xy.y > 0 ) {
				xy.y = xy.y - 1;
				update_cursor( xy, oldxy );
				m_change = true;
			}
			break;
		case 'P':         //down arrow
			if( xy.y < 14 ) {
				xy.y = xy.y + 1;
				update_cursor( xy, oldxy );
				m_change = true;
			}
			break;
		case (int)13:
      Tower *t = new Laser();    //TODO: menu to choose a tower
      if (gs->player->get_money() >= t->get_cost() && gs->map->check_can_build(const_cast<coord &>(gs->cursor->get_coord()))) {      //check if player has enough money, and if the tile can be built on top of(if it's empty and if just a "plain" tile, ie. not path or base)
        coord tower_xy = gs->cursor->get_coord();
        gs->player->set_money(gs->player->get_money() - t->get_cost());   //update player money
        tower_xy.layer = 1;                                               //makes sure that tower is displayed on proper layer
			  t->set_coord(tower_xy);
		  	gs->map->update(t);                                               //update with tower
      }
      else
        delete t;

      gs->map->clear_cursor(gs->cursor->get_coord());                    //clear cursor at current location
			switch_to_edit();
			m_change = true;
		}
	}
	
}
Ejemplo n.º 14
0
Float BuildTower(Script * script)
{
	if (script->VerifyArguments(2) == true)
	{
		Word * targetWord = script->GetNextWord();
		Word * posWord = script->GetNextWord();

		Point2D position(0, 0);
		Point2D * pos = (Point2D *)(uint32)posWord->value;
		if (pos != NULL)
		{
			position.SetValues(pos->GetX(), pos->GetY());
		}
		else
		{
			return false;
		}

		if ((IntervalCheck(position.GetX(), 1, GRID_SIZE - 2) == true) && (IntervalCheck(position.GetY(), 1, GRID_SIZE - 2) == true))
		{
			if (targetWord->type == POINTER)
			{
				Object * target = script->GetTarget(targetWord);
				if ((target != NULL) && (target->CheckType(OBJ_TYPE_TOWER) == true))
				{
					Grid * grid = WorldGame.GetGrid();
					Tower * tower = (Tower *)target;

					//To bypass grid auto-filling
					tower->SetState(false);

					Point2D towerCoords = tower->GetPosition();
					towerCoords.SetValues((towerCoords.GetX() - 80)/32, (towerCoords.GetY() - 80)/32);
					grid->SetPath(towerCoords, 0);	

					if (BuildTower(tower->GetTowerType(), position, true) == true)
					{
						Tower * newTower = grid->GetData(Point2D(position.GetX(), position.GetY()));
						tower->SetState(true);
						grid->FindPath(Origin);
						newTower->Copy(*tower);
						newTower->SetUInt32Value(TOWER_VAR_BUILD_TIME, GetGameTime());
						return true;
					}
					else
					{
						tower->SetState(true);
						grid->FindPath(Origin);
					}
				}
			}
			else if ((targetWord->type == NUMERIC) && (IntervalCheck(targetWord->value, 1, GetTowerDataSize()) == true))
			{
				return (BuildTower(targetWord->value, position, true));
			}
		}
	}
	return false;
}
Ejemplo n.º 15
0
// Function: main()
int main(int argc, char ** argv)
{
    PA_Init();    // Initializes PA_Lib
    PA_InitVBL(); // Initializes a standard VBL
    PA_InitText(1,1);
    Drawable cursor(0,0,0);
    cursor.Load(0, 0, (void*)pal_cursor, (void*)gfx_cursor, OBJ_SIZE_16X16, 1);
    setupRotations();
    u8 c = 0;
    u8 x = 0;
    u8 y = 0;
    for (y = 0; y != 8; ++y) {
        for (x = 0; x != 8; ++x) {
            u16 i = y*8+x;
            if (grid[i] == 1) {
                Tower tower = Tower(SPRITE_TOWER_BASE+c, x*16, y*16);
                tower.Load(0, 1, (void*)pal_tower, (void*)gfx_tower, OBJ_SIZE_16X16, 1);
                tower_list.push_back(tower);
                PA_SetSpriteRotEnable(0, tower.sprite, c);
                ++c;
            }
        }
    }

    s16 angle = 0;

	// Infinite loop to keep the program running
	while (1)
	{
	    u8 i = 0;
        for (tlist_it it = tower_list.begin(); it != tower_list.end(); ++it) {
            angle = (*it).GetAngleTo(cursor);
            PA_SetRotsetNoZoom(0, i, angle);
            ++i;
        }
        PA_OutputText(1, 0, 0, "Angle: %03d", angle);
        PA_OutputText(1, 0, 1, "Angle2: %03d", angle);
        PA_OutputText(1, 0, 2, "Cursor: %03d,%03d", cursor.position.x, cursor.position.y);
        if (Stylus.Held) {
            cursor.position.x = Stylus.X;
            cursor.position.y = Stylus.Y;
        } else {
            cursor.position.x += (Pad.Held.Right - Pad.Held.Left);
            cursor.position.y += (Pad.Held.Down - Pad.Held.Up);
        }
        cursor.Draw();
        PA_WaitForVBL();
	}

	return 0;
} // End of main()
Ejemplo n.º 16
0
Tower best_tower(const Box& b, const list<Tower>& tows){
  list<Tower>::const_iterator it;
  double best_height = 0;
  Tower res;
  for(it=tows.begin(); it!=tows.end(); it++){
    double new_height = b.height() + tower_height(*it);
    if(can_stack(b, *it) && new_height > best_height){
      best_height = new_height;
      res = *it;
      res.push_front(b); 
    }
  } 
  return res;
}
Ejemplo n.º 17
0
//-----------------------------------------------------------------------------
// delete vertex and index buffers
void Wreck::deleteBuffers()
{
  delete m_indexes;
  m_indexes = NULL;
  delete m_vertexes;
  m_vertexes = NULL;

  for (int i = 0; i < m_towers.length(); i++)
  {
    Tower* tower = (Tower*) m_towers[i];
    if (tower != NULL)
      tower->deleteBuffers();
  }
}
Ejemplo n.º 18
0
bool TowerRules::UpgradeToEarth(Ref* p, Ref & u)
{
    Tower *t = (Tower*)&u;
    if( t->GetElement() == ElementalAffinity::None && ((Player*)p)->GetCurrency() >= this->earthUpgradeCost )
    {
        t->SetElement(ElementalAffinity::Earth);
        ((Player*)p)->RemoveCoins(this->earthUpgradeCost);
        return true;
    }
    else
    {
        return false;
    }
}
Ejemplo n.º 19
0
Tower* Tower::create(ValueMap model)
{
	Tower *ret = new Tower(model);
	if (ret && ret->init())
	{
		ret->autorelease();
		return ret;
	}
	else
	{
		CC_SAFE_DELETE(ret);
		return nullptr;
	}
}
Ejemplo n.º 20
0
Tower *Tower::create(int id)
{
	Tower *ret = new Tower(id);
	if (ret && ret->init())
	{
	ret->autorelease();
	return ret;
	}
	else
	{
	CC_SAFE_DELETE(ret);
	return nullptr;
	}
}
Ejemplo n.º 21
0
bool TowerRules::UpgradeAttackSpeed(Ref* p, Ref & u)
{
    Tower *t = (Tower*)&u;
    if( ((Player*)p)->GetCurrency() >= this->GetSpeedUpgradeCost(*t) )
    {
        ((Player*)p)->RemoveCoins(this->GetSpeedUpgradeCost(*t));
        t->inbetweenAttacksPeriod = t->inbetweenAttacksPeriod - this->attackSpeedSub;
        t->IncreaseSpeedUpgradesDone();
        return true;
    }
    else
    {
        return false;
    }
}
Ejemplo n.º 22
0
bool TowerRules::UpgradeAttackPower(Ref* p, Ref & u)
{
    Tower *t = (Tower*)&u;
    if( ((Player*)p)->GetCurrency() >= this->GetAttackUpgradeCost(*t) )
    {
        ((Player*)p)->RemoveCoins(this->GetAttackUpgradeCost(*t));
        t->attackPoints = t->attackPoints + this->attackDamageAdd;
        t->IncreaseAttackUpgradesDone();
        return true;
    }
    else
    {
        return false;
    }
}
Ejemplo n.º 23
0
	void moveDisks(int n, Tower& dest,Tower& buffer){
		if(n>0){
			moveDisks(n-1,buffer,dest);
			moveTopTo(dest);
			buffer.moveDisks(n-1,dest,*this);
		}
	}
Ejemplo n.º 24
0
void UILayer::addTouchableTower(TowerTypes towerType, cocos2d::CCPoint position){
	if (towers->Buy(towerType)){
		Tower *newTower = towers->createTower(towerType, position);
		this->addChild(newTower->getSprite(), 100);

		TouchableSprite *tSprite = new TouchableSprite();
		tSprite->towerType = towerType;
		tSprite->tower = newTower;
		tSprite->spriteType = TOWER_ON_SCENE;
		tSprite->sprite = newTower->getSprite();
		tSprite->cellX = 0;
		tSprite->cellY = 0;

		addTouchableSprite(tSprite);
	}
}
Ejemplo n.º 25
0
//-----------------------------------------------------------------------------
// render the wreck
void Wreck::render()
{
  // set drawing parameters
  mgDisplay->setMatColor(1.0, 1.0, 1.0);
//  mgDisplay->setCulling(false);
  mgDisplay->setTransparent(false);

  // draw triangles using texture and shader
  mgDisplay->setShader("litTextureArray");
  mgDisplay->setTexture(m_texture);
  mgDisplay->draw(MG_TRIANGLES, m_vertexes, m_indexes);

//  mgDisplay->setCulling(true);

  mgMatrix4 baseModel;
  mgDisplay->getModelTransform(baseModel);

  Tower* tower = NULL;
  mgMatrix4 model;
  for (int i = 0; i < 3; i++)
  {
    tower = (Tower*) m_towers[i*2+0];
    if (tower != NULL)
    {
      model.loadIdentity();
      model.rotateXDeg(-90);
      model.translate(0, 11, 65+40*i);
      model.rotateZDeg(120*i);
      mgDisplay->appendModelTransform(model);
      tower->render();
      mgDisplay->setModelTransform(baseModel);
    }

    tower = (Tower*) m_towers[i*2+1];
    if (tower != NULL)
    {
      model.loadIdentity();
      model.rotateXDeg(-90);
      model.rotateZDeg(180);
      model.translate(0, -11, 65+40*i);
      model.rotateZDeg(120*i);
      mgDisplay->appendModelTransform(model);
      tower->render();
      mgDisplay->setModelTransform(baseModel);
    }
  }
}
Ejemplo n.º 26
0
// Move disk from A to B
void
Tower::move(Tower &A, Tower &B)
{
    int top_A = (A.stk).top();
    B.put(top_A);
    (A.stk).pop();
    // Print movement information
    cout << A.num << ' ' << B.num << "\n";
}
Ejemplo n.º 27
0
 void MoveDisks(int n, Tower d, Tower buffer)
 {
     if( n > 0 ) {
         // put n-1 elements to the buffer Tower
         MoveDisks(n - 1 , buffer, d);
         // move one last element to the destination
         MoveTopTo(d);
         // put those n-1 back to the destination Tower!
         buffer.moveDisks(n-1, d,this);
         // Done
     }
 }
Ejemplo n.º 28
0
//shows the strength of a tower
int TowerRules::GetStrength(Ref & t)
{
    Tower * to = (Tower*) &t;
    
    int a;
    
    // 1 second / inbetweenAttacksPeriod 
    if(to->GetElement() == ElementalAffinity::Fire)
    {
        //return ((to->attackPoints + this->addFireDamage) * (1/to->inbetweenAttacksPeriod)) / 50;
        a = ((this->elementsAmplifier * to->attackPoints) + this->addFireDamage) + (1/to->inbetweenAttacksPeriod) / 1000;
        //std::cout << "\n\n test strength test: " << a << "\n\n";
        return a;
    }
    else if(to->GetElement() == ElementalAffinity::Earth)
    {
        a = ((this->elementsAmplifier * to->attackPoints) + this->addEarthDamage) + (1/to->inbetweenAttacksPeriod) / 1000;
        //std::cout << "\n\n test strength test: " << a << "\n\n";
        return a;
    }
    else if(to->GetElement() == ElementalAffinity::Water)
    {
        a = ((this->elementsAmplifier * to->attackPoints) + this->addWaterDamage) + (1/to->inbetweenAttacksPeriod) / 1000;
        //std::cout << "\n\n test strength test: " << a << "\n\n";
        return a;
    }
    else if(to->GetElement() == ElementalAffinity::Shock)
    {
        a = ((this->elementsAmplifier * to->attackPoints) + this->addShockDamage) + (1/to->inbetweenAttacksPeriod) / 1000;
        //std::cout << "\n\n test strength test: " << a << "\n\n";
        return a;
    }
    else // element == none
    {
        //return ((to->attackPoints) * (1/to->inbetweenAttacksPeriod)) /50 ;
        a = ((this->elementsAmplifier * to->attackPoints) ) + (1/to->inbetweenAttacksPeriod) / 1000;
        //std::cout << "\n\n test strength test: " << a << "\n\n";
        return a;
    }
}
Ejemplo n.º 29
0
void StartScene::addTower(Point pos, Tower::TowerType towerType)
{
    DataModel *m = DataModel::getModel();
    Tower *target = NULL ;
    Point towerLoc = this->tileCoordForPosition(pos);
    int tileGid = this->_background->tileGIDAt(towerLoc);
    Value props = this->_tileMap->propertiesForGID(tileGid);
    ValueMap map = props.asValueMap();
    int type_int = map.at("buildable").asInt();
    target = Tower::createWithType(towerType);
    if (target->price>m->currentMoney) {
        MessageBox("no enough money!","");
        return;
    }
    if (1 == type_int)
    {
//        std::string targetPos = "pos.x = "+std::to_string(towerLoc.x)+" pos.y = "+std::to_string(towerLoc.y);
//        log(targetPos.c_str());
        bool buildable = true;
        for (auto point = m->buildedPoints.equal_range(towerLoc.x); point.first!=point.second; ++point.first) {
            if (towerLoc.y==point.first->second) {
                buildable = false;
                break;
            }
        }
        if (buildable) {
            m->buildedPoints.insert(std::make_pair(towerLoc.x, towerLoc.y));
            target->setPosition(ccp((towerLoc.x * 32) + 16, this->_tileMap->getContentSize().height - (towerLoc.y * 32) - 16));
            this->addChild(target,1);
            target->setTag(1);
            m->currentMoney -= target->price;
            money->setText(to_string(m->currentMoney));
            m->towers.pushBack(target);
        }
    }
    else
    {
        log("Tile Not Buildable");
    }
}
Ejemplo n.º 30
0
std::string Battle::Tower::GetInfo(const Castle & cstl)
{
    const char* tmpl = _("The %{name} fires with the strength of %{count} Archers");
    const char* addn = _("each with a +%{attack} bonus to their attack skill.");

    std::vector<int> towers;
    std::string msg;

    if(cstl.isBuild(BUILD_CASTLE))
    {
	towers.push_back(TWR_CENTER);

	if(cstl.isBuild(BUILD_LEFTTURRET)) towers.push_back(TWR_LEFT);
	if(cstl.isBuild(BUILD_RIGHTTURRET)) towers.push_back(TWR_RIGHT);

	for(std::vector<int>::const_iterator
	    it = towers.begin(); it != towers.end(); ++it)
	{
    	    Tower twr = Tower(cstl, *it);

    	    msg.append(tmpl);
    	    StringReplace(msg, "%{name}", twr.GetName());
    	    StringReplace(msg, "%{count}", twr.GetCount());

	    if(twr.GetBonus())
	    {
		msg.append(", ");
		msg.append(addn);
    		StringReplace(msg, "%{attack}", twr.GetBonus());
	    }
	    else
		msg.append(".");

	    if((it + 1) != towers.end())
    		msg.append("\n \n");
	}
    }

    return msg;
}