#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define WARRIOR_NUM 5
#define WEAPON_NUM 3
#define COLOR_RED 0
#define COLOR_BLUE 1
#define COLOR_NONE 3
enum{DRAGON,NINJA,ICEMAN,LION,WOLF};
enum{WEAPON_SWORD,WEAPON_BOMB,WEAPON_ARROW};
enum EEventType{EVENT_BORN,EVENT_LION_RUN,EVENT_MARCH,EVENT_ARROW,EVENT_BOMB,EVENT_ATTACK,EVENT_FIGHTBACK,
EVENT_KILLED,EVENT_YELL,EVENT_EARNMONEY,EVENT_FLAG,EVENT_REACH,EVENT_CITYTAKEN,EVENT_PRINTMONEY,
EVENT_WARRIOR_REPORT};
class CHeadquarter;
class CKingdom;
class CWarrior;
class CCity;
class CWeapon;
typedef CWarrior* PWARRIOR;
string MyIntToStr(int n)
{
char szTmp[300];
sprintf(szTmp,"%d",n);
return szTmp;
}
class CWeapon
{
public:
int nKindNo;
int nForce;
static const char* Names[WEAPON_NUM];
static int nArrowForce;
bool operator<(const CWeapon& w)
{
return w.nKindNo<nKindNo;
}
};
class CWarrior
{
friend class CHeadquarter;
friend bool MyCompare(const PWARRIOR& p1,const PWARRIOR& p2);
protected:
int nId;
int nStrength;
int nForce;
int nCityNo;
bool bShotToDeath;
CHeadquarter* pHeadquarter;
public:
static int InitialForce[WARRIOR_NUM];
static int InitialLifeValue[WARRIOR_NUM];
static const char* Names[WARRIOR_NUM];
CWarrior(int nId_,int nStrength_,int nForce_,int nCityNo_,CHeadquarter* pHeadquarter_);
virtual ~CWarrior();
virtual bool Runaway();
virtual bool HasBomb();
virtual int GetSwordForce();
virtual int UseSword();
virtual void AddMorale(double a);
virtual void EarnWeapons(CWarrior* pEnemy);
virtual string ReportWeapons();
virtual bool VirtualAttack(CWarrior *pEnemy);
virtual bool VirtualFightback(CWarrior* pEnemy);
virtual int Attack(CWarrior* pEnemy);
virtual int HurtedBy(CWarrior *pEnemy);
virtual void FightBack(CWarrior* pEnemy);
virtual void Killed();
virtual string GetName() = 0;
virtual void March();
virtual int ShootArrow();
int AttackedByArrow(int nArrowForce);
string GetColorStr();
int GetColor();
int GetStrength();
int GetForce();
void SetStrength(int n);
void SetForce(int n);
int GetPosition();
};
bool MyCompare( const PWARRIOR & p1, const PWARRIOR & p2)
{
if( p1->GetColor() == COLOR_RED)
return p1->nCityNo > p2->nCityNo;
else
return p1->nCityNo < p2->nCityNo;
}
class CWeaponWarrior:public CWarrior
{
public:
vector<CWeapon> vwp;
public:
CWeaponWarrior(int nId_,int nStrength_,int nForce_,int nCityNo_,CHeadquarter* pHeadquarter_,int nWeaponNum);
bool HasBomb();
int GetSwordForce();
int UseSword();
int ShootArrow();
string ReportWeapons();
};
class CDragon:public CWeaponWarrior
{
friend class CHeadquarter;
private:
double fMorale;
public:
CDragon(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_);
virtual int Attack( CWarrior * p) ;
void FightBack(CWarrior * pEnemy);
void AddMorale(double a);
virtual string GetName();
};
class CNinja:public CWeaponWarrior
{
friend class CHeadquarter;
public:
CNinja(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_);
virtual int HurtedBy(CWarrior * pEnemy);
virtual string GetName();;
bool VirtualFightback( CWarrior * pEnemy);
};
class CIceman:public CWeaponWarrior
{
friend class CHeadquarter;
private:
int nSteps;
public:
CIceman(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_);
virtual void March() ;
virtual string GetName() ;;
};
class CLion:public CWarrior
{
friend class CHeadquarter;
private:
int nLoyalty;
public:
static int nLoyaltyDec;
CLion(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_);
int HurtedBy(CWarrior * pEnemy);
void FightBack(CWarrior * pEnemy);
int Attack( CWarrior * pEnemy) ;
virtual string GetName();
bool Runaway ();
};
class CWolf:public CWeaponWarrior
{
friend class CHeadquarter;
private:
int nEnemyKilled;
public:
CWolf(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_);
virtual int Attack( CWarrior * pEnemy);
virtual string GetName();
void EarnWeapons( CWarrior * pEnemy);
};
class CHeadquarter
{
friend class CWarrior;
friend class CWolf;
friend class CDragon;
friend class CIceman;
friend class CLion;
friend class CNinja;
private:
int nBloodMoney ;
int nMoney;
int nEnemys;
int nWarriorNo;
list<CWarrior * > lstWarrior;
int nColor;
CKingdom * pKingdom;
int nCityNo;
CHeadquarter * pEnemyheadquarter;
vector<CWarrior *> vAwardList;
public:
static int MakingSeq[2][WARRIOR_NUM];
CHeadquarter(int nColor_, int nMoney_,int nCityNo_ );
~CHeadquarter();
void SetEnemy( CHeadquarter * p);
void SetKingdom( CKingdom * p);
void AddEvent( EEventType eType, int nCityNo, int nColor,const string & sEventString);
void PrintMoney();
string GetColorStr();
int GetColor();
void LionRunaway();
void Bomb();
void ShootArrow();
void WarriorBorn();
void AddToAwardList( CWarrior * pWarrior);
void GiveAward();
void WarriorsMarch(int nEnemyHeadquterCityNo );
void WarriorsAttack();
void WarriorsReport();
void EnemyReach();
void WarriorsGetFreeMoney(int);
CWarrior * QueryCityWarrior( int nCityNo);
void EarnBloodMoney( CWarrior * p, int nCityNo);
void AddBloodMoney();
};
class CCity
{
private:
int nFlagColor;
int nNo;
int nLastWinWarriorColor;
public:
int nMoney;
CCity();
void SetNo(int nNo_);
void AddMoney();
int MoneyTaken();
void SetFlagColor(int nColor);
int GetFlagColor();
int GetTotalMoney();
bool CWarriorWin(int nColor);
void WarDraw();
};
class CEvent
{
private:
EEventType eEventType;
int nTime;
int nCityNo;
int nColor;
string sDescribe;
public:
CEvent(EEventType eEventType_,int nTime_,int nCity_,int nColor_,const string &s);
void Output();
bool operator<(const CEvent &e2) const
{
if(nTime<e2.nTime)
return true;
else if(nTime>e2.nTime)
return false;
if(eEventType == e2.eEventType && eEventType == EVENT_WARRIOR_REPORT)
{
if(nColor < e2.nColor)
return true;
else if(nColor == e2.nColor)
return nCityNo<e2.nCityNo;
else
return false;
}
if(nCityNo < e2.nCityNo)
return true;
else if(nCityNo > e2.nCityNo)
return false;
if(eEventType < e2.eEventType)
return true;
else if(eEventType > e2.eEventType)
return false;
if(nColor<e2.nColor)
return true;
else
return false;
}
};
class CKingdom
{
friend class CHeadquarter;
private:
CHeadquarter Red,Blue;
int nTimeInMinutes;
vector<CEvent> vEvent;
vector<CCity> vCity;
int nEndTime;
int nCityNum;
public:
CKingdom(int nCityNum_,int nInitMoney);
void Run(int T);
int TimePass(int nMinutes) ;
string SystemTimeStr();
void WarDraw( int nCityNo);
void KWarriorWin( CWarrior * pWarrior);
int GetTime();
void WarEnd();
void OutputResult();
void AddEvent( EEventType eType, int nCityNo, int nColor, const string & sEventString);
int GetCityFlagColor( int nCityNo);
int QueryCityMoney( int nNo);
void TakeCityMoney( int nNo);
};
CCity::CCity():nFlagColor(COLOR_NONE),nMoney(0),nLastWinWarriorColor(COLOR_NONE){}
void CCity::SetNo(int nNo_)
{
nNo = nNo_;
}
void CCity::AddMoney()
{
nMoney += 10;
}
int CCity::MoneyTaken()
{
int nTemp = nMoney;
nMoney = 0;
return nTemp;
}
void CCity::SetFlagColor(int nColor)
{
nFlagColor = nColor;
}
int CCity::GetFlagColor()
{
return nFlagColor;
}
int CCity::GetTotalMoney()
{
return nMoney;
}
bool CCity::CWarriorWin(int nColor)
{
if(nColor == nLastWinWarriorColor)
{
if(nFlagColor != nColor)
{
SetFlagColor(nColor);
return true;
}
else
return false;
}
nLastWinWarriorColor = nColor;
return false;
}
void CCity::WarDraw()
{
nLastWinWarriorColor = COLOR_NONE;
}
CEvent::CEvent(EEventType eEventType_,int nTime_,int nCityNo_,int nColor_,const string &s):
eEventType(eEventType_),nTime(nTime_),nCityNo(nCityNo_),nColor(nColor_),sDescribe(s){}
void CEvent::Output()
{
char szTime[20];
sprintf(szTime,"%03d:%02d",nTime/60,nTime%60);
cout<<szTime<<" "<<sDescribe<<endl;
}
CWarrior::CWarrior(int nId_,int nStrength_,int nForce_,int nCityNo_,CHeadquarter* pHeadquarter_):
nId(nId_),nStrength(nStrength_),nForce(nForce_),nCityNo(nCityNo_),bShotToDeath(false),
pHeadquarter(pHeadquarter_){}
CWarrior::~CWarrior(){}
bool CWarrior::Runaway() { return false; }
bool CWarrior::HasBomb() { return false; }
int CWarrior::GetSwordForce() { return 0;}
int CWarrior::UseSword(){ return 0; }
void CWarrior::AddMorale(double a) { };
void CWarrior::EarnWeapons( CWarrior * pEnemy) { }
string CWarrior::ReportWeapons() { return "";}
bool CWarrior::VirtualAttack(CWarrior *pEnemy)
{
if(nStrength>0 && nForce + GetSwordForce() >= pEnemy->nStrength)
return true;
else
return false;
}
bool CWarrior::VirtualFightback(CWarrior* pEnemy)
{
if(nStrength>0 && nForce/2 + GetStrength() >= pEnemy->nStrength)
return true;
else
return false;
}
int CWarrior::AttackedByArrow(int nArrowForce)
{
nStrength -= nArrowForce;
if( nStrength <= 0 ) {
nStrength = 0;
bShotToDeath = true;
}
return nStrength;
}
int CWarrior::Attack(CWarrior* pEnemy)
{
if(pEnemy->GetStrength()<=0)
{
return 1;
}
char szTmp[200];
sprintf(szTmp," with %d elements and force %d",nStrength,nForce);
string sEventString = GetName() + "attacked " + pEnemy->GetName() + string(" in city ") + MyIntToStr(nCityNo) + szTmp;
pHeadquarter->AddEvent(EVENT_ATTACK,nCityNo,GetColor(),sEventString);
if(pEnemy->HurtedBy(this)<=0)
return 1;
if(nStrength<=0)
{
Killed();
return -1;
}
return 0;
}
int CWarrior::HurtedBy(CWarrior* pEnemy)
{
int nSwordForce = pEnemy->UseSword();
nStrength -= pEnemy->GetForce() + nSwordForce;
if(nStrength<=0)
{
Killed();
return -1;
}
else
{
string sEventString = GetName() + " fought back against " + pEnemy->GetName() + " in city " + MyIntToStr(nCityNo);
pHeadquarter->AddEvent(EVENT_FIGHTBACK,nCityNo,GetColor(),sEventString);
FightBack(pEnemy);
return nStrength;
}
}
void CWarrior::FightBack(CWarrior* pEnemy)
{
int nSwordForce = UseSword();
pEnemy->nStrength -= nForce/2 + nSwordForce;
}
void CWarrior::Killed()
{
string sEventString = GetName() + " was killed in city " + MyIntToStr(nCityNo);
pHeadquarter->AddEvent(EVENT_KILLED,nCityNo,GetColor(),sEventString);
}
void CWarrior::March()
{
if(GetColor() == COLOR_RED)
nCityNo++;
else
nCityNo--;
}
int CWarrior::GetColor()
{
return pHeadquarter->GetColor();
}
string CWarrior::GetColorStr()
{
return pHeadquarter->GetColorStr();
}
int CWarrior::GetStrength()
{
return nStrength;
}
int CWarrior::GetForce()
{
return nForce;
}
void CWarrior::SetStrength(int n)
{
nStrength = n;
}
void CWarrior::SetForce(int n)
{
nForce = n;
}
int CWarrior::GetPosition()
{
return nCityNo;
}
int CWarrior::ShootArrow()
{
return 0;
}
CWeaponWarrior::CWeaponWarrior(int nId_,int nStrength_,int nForce_,int nCityNo_,CHeadquarter* pHeadquarter_,int nWeaponNum):
CWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_),vwp(nWeaponNum)
{
}
bool CWeaponWarrior::HasBomb()
{
for(int i = 0;i<vwp.size();i++)
{
if(vwp[i].nKindNo == WEAPON_BOMB)
return true;
}
return false;
}
int CWeaponWarrior::GetSwordForce()
{
for(int i = 0;i<vwp.size();i++)
{
if(vwp[i].nKindNo == WEAPON_SWORD)
return vwp[i].nForce;
}
return 0;
}
int CWeaponWarrior::UseSword()
{
for(int i = 0;i<vwp.size();i++)
{
if(vwp[i].nKindNo == WEAPON_SWORD)
{
int nTmp = vwp[i].nForce;
vwp[i].nForce *= 0.8;
if(vwp[i].nForce == 0)
vwp.erase(vwp.begin() + i);
return nTmp;
}
}
return 0;
}
int CWeaponWarrior::ShootArrow()
{
for(int i = 0;i<vwp.size();i++)
{
if(vwp[i].nKindNo == WEAPON_ARROW)
{
vwp[i].nForce--;
if(vwp[i].nForce == 0)
vwp.erase(vwp.begin() + i);
return CWeapon::nArrowForce;
}
}
return 0;
}
string CWeaponWarrior::ReportWeapons()
{
if(vwp.size() == 0)
return "";
string rs = " has ";
sort(vwp.begin(),vwp.end());
bool bFirst = true;
for(int i = 0;i<vwp.size();i++)
{
if(!bFirst)
rs+=",";
else
bFirst = false;
rs+=CWeapon::Names[vwp[i].nKindNo];
if(vwp[i].nKindNo != WEAPON_BOMB)
rs+=string("(") + MyIntToStr(vwp[i].nForce) + string(")");
}
return rs;
}
CDragon::CDragon(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWeaponWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_,1)
{
vwp[0].nKindNo = nId_%WEAPON_NUM;
if(vwp[0].nKindNo == WEAPON_SWORD)
{
vwp[0].nForce == nForce_*0.2;
if(vwp[0].nForce == 0)
vwp.clear();
}
else if(vwp[0].nKindNo == WEAPON_ARROW)
vwp[0].nForce = 3;
fMorale = pHeadquarter->nMoney/(double)CWarrior::InitialLifeValue[0];
}
int CDragon::Attack( CWarrior * p)
{
int nRetVal = CWarrior::Attack(p);
if( nRetVal != -1 && fMorale > 0.8) {
string sEventString = GetName() + " yelled in city " + MyIntToStr(nCityNo);
pHeadquarter->AddEvent( EVENT_YELL, nCityNo, GetColor(), sEventString);
if( nRetVal == 0)
fMorale -= 0.2;
else
fMorale += 0.2;
}
return nRetVal;
}
void CDragon::FightBack(CWarrior * pEnemy)
{
CWarrior::FightBack (pEnemy);
if( pEnemy->GetStrength() > 0 )
fMorale -= 0.2;
else
fMorale += 0.2;
}
void CDragon::AddMorale(double a)
{
fMorale += a;
};
string CDragon::GetName()
{
return pHeadquarter->GetColorStr() + " dragon " + MyIntToStr(nId);
}
CNinja::CNinja(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWeaponWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_,2)
{
bool bDeleteSword = false;
vector<CWeapon>::iterator p;
for( int i = 0;i < 2;i ++) {
vwp[i].nKindNo =( nId_ + i )% WEAPON_NUM;
if( vwp[i].nKindNo == WEAPON_SWORD ) {
vwp[i].nForce = nForce_ * 0.2;
if(vwp[i].nForce == 0) {
bDeleteSword = true;
p = vwp.begin() + i;
}
}
else if( vwp[i].nKindNo == WEAPON_ARROW )
vwp[i].nForce = 3;
}
if( bDeleteSword)
vwp.erase (p);
}
int CNinja::HurtedBy(CWarrior * pEnemy)
{
int nSwordForce = pEnemy->UseSword();
nStrength -= pEnemy->GetForce() + nSwordForce;
if( nStrength <= 0 ) {
Killed();
return -1;
}
return nStrength;
}
bool CNinja::VirtualFightback( CWarrior * pEnemy)
{
return false;
}
string CNinja::GetName()
{
return pHeadquarter->GetColorStr() + " ninja " + MyIntToStr(nId);
}
CIceman::CIceman(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWeaponWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_,1),nSteps(0)
{
vwp[0].nKindNo = nId % WEAPON_NUM;
if( vwp[0].nKindNo == WEAPON_SWORD ) {
vwp[0].nForce = nForce_ * 0.2;
if( vwp[0].nForce == 0)
vwp.clear();
}
else if( vwp[0].nKindNo == WEAPON_ARROW )
vwp[0].nForce = 3;
}
void CIceman::March()
{
CWarrior::March();
nSteps = ( nSteps + 1 ) %2;
if( nSteps == 0) {
if( nStrength - 9 > 1 )
nStrength -= 9;
else
nStrength = 1;
nForce += 20;
}
}
string CIceman::GetName()
{
return pHeadquarter->GetColorStr() + " iceman " + MyIntToStr(nId);
}
CLion::CLion(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):CWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_)
{
nLoyalty = pHeadquarter->nMoney;
}
int CLion::Attack(CWarrior *pEnemy)
{
int nTmp = nStrength;
int nRetVal = CWarrior::Attack(pEnemy);
if(nRetVal == -1)
pEnemy->SetStrength(pEnemy->GetStrength() + nTmp);
else if(nRetVal != 1)
nLoyalty-=CLion::nLoyaltyDec;
return nRetVal;
}
int CLion::HurtedBy(CWarrior * pEnemy)
{
int nSwordForce = pEnemy->UseSword();
if( nStrength - pEnemy->GetForce() - nSwordForce <= 0 ) {
pEnemy->SetStrength( pEnemy->GetStrength() + nStrength );
nStrength = 0;
Killed();
return -1;
}
nStrength -= pEnemy->GetForce() + nSwordForce;
string sEventString = GetName() + " fought back against " + pEnemy->GetName() + " in city " + MyIntToStr(nCityNo);
FightBack(pEnemy);
pHeadquarter->AddEvent(EVENT_FIGHTBACK,nCityNo, GetColor(),sEventString);
return nStrength;
}
void CLion::FightBack(CWarrior * pEnemy)
{
CWarrior::FightBack(pEnemy);
if(pEnemy->GetStrength()>0)
nLoyalty -= CLion::nLoyaltyDec;
}
bool CLion::Runaway ()
{
return nLoyalty <= 0;
}
string CLion::GetName()
{
return pHeadquarter->GetColorStr() + " lion " + MyIntToStr(nId);
}
CWolf::CWolf(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWeaponWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_,0),nEnemyKilled(0)
{
}
int CWolf::Attack( CWarrior * pEnemy)
{
int nRetVal = CWarrior::Attack(pEnemy);
if( nRetVal > 0 )
EarnWeapons( pEnemy);
return nRetVal;
}
void CWolf::EarnWeapons( CWarrior * pEnemy)
{
int i,j;
if(pEnemy->ReportWeapons() != "")
{
CWeaponWarrior* p = (CWeaponWarrior*)pEnemy;
for(i = 0;i<p->vwp.size();i++)
{
bool bAlreadyHas = false;
for(j = 0;j<vwp.size();j++)
{
if(p->vwp[i].nKindNo == vwp[j].nKindNo)
{
bAlreadyHas = true;
break;
}
}
if(!bAlreadyHas)
vwp.push_back(p->vwp[i]);
}
}
}
string CWolf::GetName()
{
return pHeadquarter->GetColorStr() + " wolf " + MyIntToStr(nId);
}
CHeadquarter::CHeadquarter(int nColor_, int nMoney_,int nCityNo_ ) : nBloodMoney(0),nMoney(nMoney_), nEnemys(0),
nWarriorNo(1),nColor(nColor_),nCityNo(nCityNo_)
{
}
CHeadquarter::~CHeadquarter()
{
list<CWarrior*> ::iterator p;
for( p = lstWarrior.begin(); p != lstWarrior.end(); p ++ )
delete (* p);
lstWarrior.clear();
}
void CHeadquarter::SetEnemy( CHeadquarter * p)
{
pEnemyheadquarter = p;
}
void CHeadquarter::SetKingdom( CKingdom * p)
{
pKingdom = p;
}
void CHeadquarter::AddEvent( EEventType eType, int nCityNo, int nColor, const string & sEventString)
{
pKingdom->AddEvent( eType,nCityNo,nColor,sEventString);
}
void CHeadquarter::PrintMoney()
{
char szTmp[100];
sprintf(szTmp,"%d",nMoney);
string sEventString = string(szTmp) + " elements in " + GetColorStr() + " headquarter";
if( nColor == COLOR_RED)
pKingdom->AddEvent( EVENT_PRINTMONEY, 0, nColor,sEventString);
else
pKingdom->AddEvent( EVENT_PRINTMONEY, pKingdom->vCity.size() + 1, nColor,sEventString);
}
string CHeadquarter::GetColorStr()
{
if( nColor == COLOR_RED)
return "red";
else
return "blue";
}
int CHeadquarter::GetColor()
{
return nColor;
}
void CHeadquarter::LionRunaway()
{
string sEventString;
list<CWarrior * >::iterator i = lstWarrior.begin();
while(i != lstWarrior.end() ) {
if( (*i)->Runaway()) {
int nCityNo = ( * i )->GetPosition();
if( nColor == COLOR_RED && nCityNo == pKingdom->nCityNum + 1 ||
nColor == COLOR_BLUE && nCityNo == 0 )
continue;
sEventString = (*i)->GetName() + " ran away";
AddEvent( EVENT_LION_RUN, ( * i )-> nCityNo, nColor,sEventString);
i = lstWarrior.erase (i);
continue;
}
i++;
}
}
void CHeadquarter::Bomb()
{
list<CWarrior * >::iterator i = lstWarrior.begin();
while( i != lstWarrior.end() ) {
int nCityNo = ( * i )->GetPosition();
if( (*i)->GetStrength () > 0 ) {
CWarrior * p = pEnemyheadquarter->QueryCityWarrior(nCityNo);
if( p ) {
bool bShouldAttack = false;
if( pKingdom->GetCityFlagColor(nCityNo) == nColor )
bShouldAttack = true;
else if( pKingdom->GetCityFlagColor(nCityNo) == COLOR_NONE) {
if( nColor == COLOR_RED && (nCityNo % 2 == 1))
bShouldAttack = true;
if( nColor == COLOR_BLUE && (nCityNo % 2 == 0))
bShouldAttack = true;
}
bool r1 = false ,r2 = false;
if( ( * i )->HasBomb()) {
if( bShouldAttack) {
if( (*i)->VirtualAttack(p) == false)
r1 = p->VirtualFightback(*i);
else
r1 = false;
}
else
r2 = p->VirtualAttack(*i);
if( r1 || r2 ) {
string sEventString = (*i)->GetName() + " used a bomb and killed " +
p->GetName();
AddEvent( EVENT_BOMB, nCityNo, GetColor(), sEventString);
i = lstWarrior.erase (i);
p->SetStrength(0);
continue;
}
}
}
}
i ++;
}
}
void CHeadquarter::ShootArrow()
{
list<CWarrior * >::iterator i;
for( i = lstWarrior.begin();i != lstWarrior.end();i ++ ) {
int nCityNo = ( * i )->GetPosition();
if( nColor == COLOR_RED ) {
nCityNo ++;
if( nCityNo == pKingdom->nCityNum + 1 )
continue ;
}
else {
nCityNo --;
if( nCityNo == 0)
continue;
}
CWarrior * p = pEnemyheadquarter->QueryCityWarrior(nCityNo);
if( p ) {
int nArrowForce = (*i)->ShootArrow();
if( nArrowForce > 0) {
string sEventString = (*i)->GetName() + " shot";
if( p->AttackedByArrow(nArrowForce) <= 0 )
sEventString += " and killed " + p->GetName();
AddEvent( EVENT_ARROW,( * i )->GetPosition(), GetColor(), sEventString);
}
}
}
}
void CHeadquarter::EnemyReach()
{
nEnemys ++;
if( nEnemys == 2 ) {
if( nColor == COLOR_RED )
AddEvent( EVENT_CITYTAKEN, nCityNo, nColor,string("red headquarter was taken"));
else
AddEvent( EVENT_CITYTAKEN, nCityNo, nColor,string("blue headquarter was taken"));
pKingdom->WarEnd();
}
}
CWarrior * CHeadquarter::QueryCityWarrior( int nCityNo)
{
list<CWarrior *>::iterator i;
for( i = lstWarrior.begin();i != lstWarrior.end();i ++ ) {
if( (* i )->GetPosition () == nCityNo)
return ( * i );
}
return NULL;
}
void CHeadquarter::AddBloodMoney()
{
nMoney += nBloodMoney;
nBloodMoney = 0;
}
void CHeadquarter::WarriorsGetFreeMoney(int nEnemyheadquarterNo )
{
list<CWarrior*>::iterator i;
for( i = lstWarrior.begin(); i != lstWarrior.end();i ++ ) {
int nCityno = ( * i )->GetPosition();
if( nCityno != 0 && nCityno != nEnemyheadquarterNo) {
CWarrior * p ;
p = pEnemyheadquarter->QueryCityWarrior(nCityno);
if( p == NULL ) {
int nMoneyEarned;
nMoneyEarned = pKingdom->QueryCityMoney(nCityno);
if( nMoneyEarned > 0 ) {
nMoney += nMoneyEarned;
pKingdom->TakeCityMoney(nCityno);
string sEventString = (*i)->GetName() + " earned " + MyIntToStr(nMoneyEarned) + " elements for his headquarter";
AddEvent( EVENT_EARNMONEY, nCityno,nColor, sEventString);
}
}
}
}
}
void CHeadquarter::WarriorsMarch(int nEnemyHeadquterCityNo)
{
list<CWarrior * >::iterator i;
string sEventString;
for( i = lstWarrior.begin();i != lstWarrior.end();i ++ ) {
int nOldPos = ( * i ) ->nCityNo ;
if( nColor == COLOR_RED ) {
if( ( * i )-> nCityNo < nEnemyHeadquterCityNo)
( *i )->March();
}
else {
if( ( * i )-> nCityNo > nEnemyHeadquterCityNo)
( *i )->March();
}
char szTmp[100];
sprintf( szTmp," with %d elements and force %d",(*i)->nStrength,(*i)->nForce);
if( nOldPos != nEnemyHeadquterCityNo) {
if (( * i )-> nCityNo == nEnemyHeadquterCityNo ) {
sEventString = (*i)->GetName() + " reached "+ pEnemyheadquarter->GetColorStr() + " headquarter" + szTmp;
AddEvent( EVENT_REACH, ( * i )-> nCityNo, nColor,sEventString);
pEnemyheadquarter->EnemyReach();
}
else {
sEventString = (*i)->GetName() + " marched to city " + MyIntToStr(( * i )->GetPosition() ) + szTmp;
AddEvent( EVENT_MARCH, ( * i )->GetPosition(), nColor,sEventString);
}
}
}
}
void CHeadquarter::WarriorsAttack()
{
list<CWarrior * >::iterator i = lstWarrior.begin();
for( i; i != lstWarrior.end();i ++) {
if( (*i)->nStrength <= 0)
continue;
int nCityNo = ( * i )->GetPosition();
if( nCityNo == 13 )
cout << "";
CWarrior * p = pEnemyheadquarter->QueryCityWarrior(nCityNo);
if( p ) {
bool bShouldAttack = false;
if( pKingdom->GetCityFlagColor(nCityNo) == nColor )
bShouldAttack = true;
else if( pKingdom->GetCityFlagColor(nCityNo) == COLOR_NONE) {
if( nColor == COLOR_RED && (nCityNo % 2 == 1))
bShouldAttack = true;
if( nColor == COLOR_BLUE && (nCityNo % 2 == 0))
bShouldAttack = true;
}
if( bShouldAttack && ( p->GetStrength () > 0 || p->bShotToDeath )) {
int nResult = ( * i )->Attack (p);
if( nResult == 1 ) {
AddToAwardList(*i);
pKingdom->KWarriorWin( * i ) ;
EarnBloodMoney( (*i), nCityNo);
}
else if( nResult < 0 ) {
pEnemyheadquarter->AddToAwardList(p);
pKingdom->KWarriorWin(p);
pEnemyheadquarter->EarnBloodMoney(p,nCityNo);
}
else {
pKingdom->WarDraw(nCityNo);
}
}
else {
if( p->bShotToDeath ) {
AddToAwardList(*i);
pKingdom->KWarriorWin( * i ) ;
EarnBloodMoney( (*i), nCityNo);
(*i) -> AddMorale(0.2);
(*i) -> EarnWeapons(p);
}
}
}
}
}
void CHeadquarter::EarnBloodMoney( CWarrior * p, int nCityNo)
{
int nMoneyEarned;
nMoneyEarned = pKingdom->QueryCityMoney(nCityNo);
if( nMoneyEarned > 0 ) {
nBloodMoney += nMoneyEarned;
pKingdom->TakeCityMoney(nCityNo);
string sEventString = p->GetName() + " earned " + MyIntToStr(nMoneyEarned) + " elements for his headquarter";
AddEvent( EVENT_EARNMONEY, nCityNo,nColor, sEventString);
}
}
void CHeadquarter::AddToAwardList( CWarrior * pWarrior)
{
vAwardList.push_back(pWarrior);
}
void CHeadquarter::GiveAward()
{
int nSize = vAwardList.size();
sort(vAwardList.begin(), vAwardList.end(),MyCompare);
for( int i = 0;i < vAwardList.size();i ++ ) {
if( nMoney >= 8 ) {
vAwardList[i]->nStrength += 8;
nMoney -= 8;
}
else
break;
}
vAwardList.clear();
}
void CHeadquarter::WarriorsReport()
{
list<CWarrior * >::iterator i = lstWarrior.begin();
string sEventString;
while(i != lstWarrior.end()) {
if( (*i)->nStrength <= 0) {
i = lstWarrior.erase (i);
continue;
}
string sEventString = (*i)->GetName();
string sWeaponStatus = (*i)->ReportWeapons();
if( sWeaponStatus != "")
sEventString += sWeaponStatus;
else
sEventString += " has no weapon";
AddEvent( EVENT_WARRIOR_REPORT, ( * i )-> nCityNo, nColor,sEventString );
i ++;
}
}
void CHeadquarter::WarriorBorn()
{
CWarrior * p = NULL;
int nSeqIdx = (nWarriorNo - 1) % 5;
if( nMoney < CWarrior::InitialLifeValue[MakingSeq[nColor][nSeqIdx]])
return ;
nMoney -= CWarrior::InitialLifeValue[MakingSeq[nColor][nSeqIdx]];
int nKindNo = MakingSeq[nColor][nSeqIdx];
switch( nKindNo ) {
case DRAGON:
p = new CDragon(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitialForce[nKindNo],nCityNo, this);
break;
case NINJA:
p = new CNinja(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitialForce[nKindNo],nCityNo, this);
break;
case ICEMAN:
p = new CIceman(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitialForce[nKindNo],nCityNo, this);
break;
case LION:
p = new CLion(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitialForce[nKindNo],nCityNo, this);
break;
case WOLF:
p = new CWolf(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitialForce[nKindNo],nCityNo, this);
break;
}
lstWarrior.push_back(p);
string sEventString = p->GetName () + " born";
if( nKindNo == LION )
sEventString += "\nIts loyalty is " + MyIntToStr(((CLion*)p)->nLoyalty);
else if( nKindNo == DRAGON) {
char szTmp[40];
sprintf(szTmp,"%.2f",((CDragon*)p)->fMorale );
sEventString += "\nIts morale is " +string(szTmp);
}
pKingdom->AddEvent( EVENT_BORN, nCityNo, nColor,sEventString);
nWarriorNo ++;
}
CKingdom::CKingdom(int nCityNum_,int nInitMoney):
nTimeInMinutes(0),Red(COLOR_RED,nInitMoney,0),Blue(COLOR_BLUE,nInitMoney,nCityNum_ + 1),
nCityNum(nCityNum_), vCity(nCityNum_ + 1)
{
for( int i = 1; i <= nCityNum;i ++ )
vCity[i].SetNo(i);
Red.SetKingdom(this);
Red.SetEnemy( &Blue);
Blue.SetKingdom(this);
Blue.SetEnemy( &Red);
nEndTime = 3000000;
}
void CKingdom::Run(int T) {
for( int t = 0; t <= T; t ++ ) {
if( TimePass(t) == 0)
return ;
}
}
int CKingdom::TimePass(int nMinutes) {
int i;
nTimeInMinutes = nMinutes;
if( nTimeInMinutes > nEndTime )
return 0;
int nRemain = nTimeInMinutes % 60;
switch( nRemain) {
case 0:
Red.WarriorBorn();
Blue.WarriorBorn();
break;
case 5:
Red.LionRunaway();
Blue.LionRunaway();
break;
case 10:
Red.WarriorsMarch(nCityNum + 1);
Blue.WarriorsMarch(0);
break;
case 20:
for( i = 0;i < vCity.size();i ++ ) {
vCity[i].AddMoney();
}
break;
case 30:
Red.WarriorsGetFreeMoney(nCityNum+1);
Blue.WarriorsGetFreeMoney(nCityNum+1);
break;
case 35:
Red.ShootArrow();
Blue.ShootArrow();
break;
case 38:
Red.Bomb();
Blue.Bomb();
break;
case 40://发生战斗
if( nTimeInMinutes == 1720 )
cout << "" ;
Red.WarriorsAttack();
Blue.WarriorsAttack();
Red.GiveAward();
Blue.GiveAward();
Red.AddBloodMoney();
Blue.AddBloodMoney();
break;
case 50:
Red.PrintMoney();
Blue.PrintMoney();
break;
case 55:
Red.WarriorsReport();
Blue.WarriorsReport();
}
return 1;
}
string CKingdom::SystemTimeStr()
{
char szTime[20];
sprintf(szTime,"%03d:%02d",nTimeInMinutes /60, nTimeInMinutes % 60);
return szTime;
}
void CKingdom::WarDraw( int nCityNo)
{
vCity[nCityNo].WarDraw();
}
void CKingdom::KWarriorWin( CWarrior * pWarrior)
{
int nCityNo = pWarrior->GetPosition();
if( vCity[nCityNo].CWarriorWin( pWarrior->GetColor()) == true ) {
string sEventString = pWarrior->GetColorStr() + " flag raised in city " + MyIntToStr( nCityNo);
AddEvent(EVENT_FLAG, nCityNo, pWarrior->GetColor(),sEventString);
}
}
int CKingdom::GetTime()
{
return nTimeInMinutes;
}
void CKingdom::WarEnd()
{
if( nEndTime == 3000000)
nEndTime = nTimeInMinutes;
}
void CKingdom::OutputResult()
{
sort(vEvent.begin(),vEvent.end());
for( int i = 0;i < vEvent.size();i ++ )
vEvent[i].Output();
}
void CKingdom::AddEvent( EEventType eType, int nCityNo,int nColor, const string & sEventString)
{
CEvent tmp(eType, nTimeInMinutes, nCityNo,nColor,sEventString);
vEvent.push_back(tmp);
}
int CKingdom::GetCityFlagColor( int nCityNo)
{
return vCity[nCityNo].GetFlagColor();
}
int CKingdom::QueryCityMoney( int nNo)
{
return vCity[nNo].GetTotalMoney();
}
void CKingdom::TakeCityMoney( int nNo)
{
vCity[nNo].MoneyTaken();
}
const char* CWeapon::Names[WEAPON_NUM] = {"sword","bomb","arrow"};
int CWeapon::nArrowForce;
int CWarrior::InitialForce[WARRIOR_NUM];
int CWarrior::InitialLifeValue[WARRIOR_NUM];
const char* CWarrior::Names[WARRIOR_NUM] = {"dragon","ninja","iceman","lion","wolf"};
int CLion::nLoyaltyDec;
int CHeadquarter::MakingSeq[2][WARRIOR_NUM] = { { 2,3,4,1,0 },{3,0,1,2,4} };
int main()
{
int nCases;
int M,N,R,K,T;
cin >> nCases;
int nCaseNo = 1;
while( nCases -- ) {
cin >> M >> N >> R >> K >> T;
CWeapon::nArrowForce = R;
CLion::nLoyaltyDec = K;
int i;
for( i = 0;i < WARRIOR_NUM;i ++ )
cin >> CWarrior::InitialLifeValue[i];
for( i = 0;i < WARRIOR_NUM;i ++ )
cin >> CWarrior::InitialForce[i];
CKingdom MyKingdom(N,M);
MyKingdom.Run(T);
cout << "Case " << nCaseNo++ << ":" << endl;
MyKingdom.OutputResult();
}
return 0;
}