#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
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 ;
}