#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
#include<cstdlib>
#include<algorithm>
using namespace std;

const float YUAN_ZHOU_LV = 3.14159265358979323846f;
const int PING_MU_KUAN = 100;
const int PING_MU_GAO = 35;
const int DI_MIAN_Y = 28;
const int ZUI_DA_GUAN_QIA = 50;
const float ZHONG_LI = 0.3f;
const float KONG_QI_ZU_LI = 0.99f;
const int ZHEN_YAN_CHI = 16;

enum KongZhiTaiYanSe{
    HEI_SE=0,
    LAN_SE=1,
    LV_SE=2,
    QING_SE=3,
    HONG_SE=4,
    ZI_SE=5,
    ZONG_SE=6,
    QIAN_HUI=7,
    AN_HUI=8,
    QIAN_LAN=9,
    QIAN_LV=10,
    QIAN_QING=11,
    QIAN_HONG=12,
    QIAN_ZI=13,
    HUANG_SE=14,
    BAI_SE=15
};

void sheZhiYanSe(int yanSe){
    HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(h,yanSe);
}

void sheZhiGuangBiaoWeiZhi(int x,int y){
    COORD zuoBiao;
    zuoBiao.X=x;
    zuoBiao.Y=y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),zuoBiao);
}

void yinCangGuangBiao(){
    HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO xinXi;
    xinXi.dwSize=100;
    xinXi.bVisible=FALSE;
    SetConsoleCursorInfo(h,&xinXi);
}

void xianShiGuangBiao(){
    HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO xinXi;
    xinXi.dwSize=100;
    xinXi.bVisible=TRUE;
    SetConsoleCursorInfo(h,&xinXi);
}

void qingPing(){
    system("cls");
}

class ShiLiang2{
public:
    float x,y;
    ShiLiang2():x(0),y(0){}
    ShiLiang2(float x,float y):x(x),y(y){}

    ShiLiang2 operator+(const ShiLiang2& qiTa)const{
        return ShiLiang2(x+qiTa.x,y+qiTa.y);
    }
    ShiLiang2 operator-(const ShiLiang2& qiTa)const{
        return ShiLiang2(x-qiTa.x,y-qiTa.y);
    }
    ShiLiang2 operator*(float suanShu)const{
        return ShiLiang2(x*suanShu,y*suanShu);
    }
    ShiLiang2 operator/(float suanShu)const{
        return ShiLiang2(x/suanShu,y/suanShu);
    }

    float moChang()const{
        return sqrt(x*x+y*y);
    }
    void guiYiHua(){
        float mo=moChang();
        if(mo>0){x/=mo;y/=mo;}
    }
    static float juLi(const ShiLiang2& a,const ShiLiang2& b){
        float dx=a.x-b.x,dy=a.y-b.y;
        return sqrt(dx*dx+dy*dy);
    }
    static float dianJi(const ShiLiang2& a,const ShiLiang2& b){
        return a.x*b.x+a.y*b.y;
    }
};

class YouXiDuiXiang{
protected:
    ShiLiang2 weiZhi;
    ShiLiang2 suDu;
    char fuHao;
    int yanSe;
    bool jiHuo;
    bool luoDi;
    bool yingYongWuLi;
    float banJing;
    int duiXiangId;
    static int xiaYiGeId;
    bool wenDing;

public:
    YouXiDuiXiang():weiZhi(0,0),suDu(0,0),fuHao(' '),yanSe(BAI_SE),
        jiHuo(true),luoDi(false),yingYongWuLi(false),banJing(1.0f),wenDing(false){
        duiXiangId=xiaYiGeId++;
    }
    YouXiDuiXiang(float x,float y,char f,int yse):weiZhi(x,y),suDu(0,0),
        fuHao(f),yanSe(yse),jiHuo(true),luoDi(false),yingYongWuLi(false),banJing(1.0f),wenDing(false){
        duiXiangId=xiaYiGeId++;
    }

    virtual void gengXin(){
        if(!jiHuo||!yingYongWuLi)return;
        suDu.y+=ZHONG_LI;
        suDu.x*=KONG_QI_ZU_LI;
        suDu.y*=KONG_QI_ZU_LI;
        weiZhi.x+=suDu.x;
        weiZhi.y+=suDu.y;

        if(weiZhi.x<1){weiZhi.x=1;suDu.x=-suDu.x*0.5f;}
        if(weiZhi.x>=PING_MU_KUAN-1){weiZhi.x=PING_MU_KUAN-2;suDu.x=-suDu.x*0.5f;}
        if(weiZhi.y<1){weiZhi.y=1;suDu.y=-suDu.y*0.2f;}

        if(weiZhi.y>=DI_MIAN_Y){
            weiZhi.y=DI_MIAN_Y;
            suDu.y=-suDu.y*0.3f;
            suDu.x*=0.8f;
            if(abs(suDu.y)<0.2f&&abs(suDu.x)<0.2f){
                suDu.x=0;suDu.y=0;luoDi=true;yingYongWuLi=false;wenDing=true;
            }
        }
        if(suDu.moChang()<0.1f&&luoDi){
            suDu.x=0;suDu.y=0;yingYongWuLi=false;wenDing=true;
        }
    }

    virtual void huaZhi(){
        if(jiHuo){
            int x=(int)weiZhi.x;
            int y=(int)weiZhi.y;
            if(x>=1&&x<PING_MU_KUAN-1&&y>=1&&y<PING_MU_GAO-1){
                sheZhiGuangBiaoWeiZhi(x,y);
                sheZhiYanSe(yanSe);
                cout<<fuHao;
                sheZhiYanSe(BAI_SE);
            }
        }
    }

    bool shiJiHuo()const{return jiHuo;}
    void sheJiHuo(bool j){jiHuo=j;}
    bool shiLuoDi()const{return luoDi;}
    void sheLuoDi(bool l){luoDi=l;}
    bool yingYongWuLiMa()const{return yingYongWuLi;}
    void sheYingYongWuLi(bool y){yingYongWuLi=y;}
    ShiLiang2 getWeiZhi()const{return weiZhi;}
    void sheWeiZhi(const ShiLiang2& w){weiZhi=w;}
    ShiLiang2 getSuDu()const{return suDu;}
    void sheSuDu(const ShiLiang2& s){suDu=s;}
    char getFuHao()const{return fuHao;}
    int getYanSe()const{return yanSe;}
    float getBanJing()const{return banJing;}
    void sheBanJing(float b){banJing=b;}
    int getId()const{return duiXiangId;}
    bool shiWenDing()const{return wenDing;}
    void sheWenDing(bool w){wenDing=w;}

    virtual ShiLiang2 pengZhuangFanYing(const ShiLiang2& suDu)const{
        ShiLiang2 fan=suDu;
        fan.x=-fan.x*0.5f;
        fan.y=-fan.y*0.3f;
        return fan;
    }

    bool jianCePengZhuang(const YouXiDuiXiang& qiTa)const{
        if(!jiHuo||!qiTa.jiHuo)return false;
        float dx=weiZhi.x-qiTa.weiZhi.x;
        float dy=weiZhi.y-qiTa.weiZhi.y;
        float ju=sqrt(dx*dx+dy*dy);
        return ju<(banJing+qiTa.banJing);
    }

    void kaiShiWuLi(float sx=0,float sy=0){
        yingYongWuLi=true;
        luoDi=false;
        wenDing=false;
        suDu.x=sx;
        suDu.y=sy;
    }
};
int YouXiDuiXiang::xiaYiGeId=1;

class Dan:public YouXiDuiXiang{
private:
    int shangHai;
public:
    bool luoDiBaoZha;
    Dan(float x,float y):YouXiDuiXiang(x,y,'@',HUANG_SE){
        sheBanJing(0.8f);
        kaiShiWuLi(0,0);
        shangHai=30;
        luoDiBaoZha=false;
    }
    void gengXin()override{
        YouXiDuiXiang::gengXin();
        if(luoDi||suDu.moChang()<0.1f){
            if(jiHuo){
                luoDiBaoZha=true;
                jiHuo=false;
            }
        }
    }
    int getShangHai()const{return shangHai;}
};

class XiaoNiao:public YouXiDuiXiang{
private:
    int xiaoNiaoLeiXing;
    bool faShe;
    bool zaiDanGong;
    float zuiDaLiDu;
    bool yongLeJiNeng;
    int xueLiang;
    int tingZhiJiShiQi;
    bool jiNengJiuXu;
    int jiNengLengQue;
    float yuanSuDuDaXiao;
    int faSheJiShiQi;
    bool jiNengChuFa;
    int ziDongJiNengJianChaJiShiQi;
    ShiLiang2 shangYiWeiZhi;

public:
    XiaoNiao(float x=10,float y=20,int leiXing=0)
        :YouXiDuiXiang(x,y,'O',QIAN_HONG),xiaoNiaoLeiXing(leiXing),faShe(false),
          zaiDanGong(true),zuiDaLiDu(18.0f),yongLeJiNeng(false),
          xueLiang(30),tingZhiJiShiQi(0),jiNengJiuXu(false),jiNengLengQue(0),
          yuanSuDuDaXiao(0),faSheJiShiQi(0),jiNengChuFa(false),
          ziDongJiNengJianChaJiShiQi(0),shangYiWeiZhi(x,y){
        if(leiXing==3)sheBanJing(2.0f);
        else sheBanJing(1.2f);

        if(leiXing==0){fuHao='O';yanSe=QIAN_HONG;}
        else if(leiXing==1){fuHao='B';yanSe=QIAN_LAN;}
        else if(leiXing==2){fuHao='Y';yanSe=HUANG_SE;}
        else if(leiXing==3){fuHao='@';yanSe=QIAN_ZI;}
        else if(leiXing==4){fuHao='G';yanSe=QIAN_LV;}
        else if(leiXing==5){fuHao='W';yanSe=BAI_SE;}
    }

    void gengXin()override{
        if(!jiHuo)return;
        if(faShe){
            ShiLiang2 dangQian=weiZhi;
            YouXiDuiXiang::gengXin();
            faSheJiShiQi++;
            ziDongJiNengJianChaJiShiQi++;
            if(jiNengLengQue>0)jiNengLengQue--;
            if(!jiNengJiuXu&&faSheJiShiQi>5)jiNengJiuXu=true;
            shangYiWeiZhi=dangQian;

            if(luoDi||suDu.moChang()<0.3f){
                tingZhiJiShiQi++;
                if(tingZhiJiShiQi>30)jiHuo=false;
                jiNengJiuXu=false;
            }
        }
    }

    void huaZhi()override{
        if(!jiHuo)return;
        if(jiNengJiuXu&&jiNengLengQue==0&&faShe&&!yongLeJiNeng&&!luoDi){
            int shanShuo=(GetTickCount()/150)%3;
            if(shanShuo==0){
                sheZhiGuangBiaoWeiZhi((int)weiZhi.x,(int)weiZhi.y);
                sheZhiYanSe(QIAN_QING);
                cout<<'@';
                sheZhiYanSe(BAI_SE);
                return;
            }
        }
        YouXiDuiXiang::huaZhi();
        if(jiNengJiuXu&&jiNengLengQue==0&&faShe&&!yongLeJiNeng&&!luoDi){
            int x=(int)weiZhi.x,y=(int)weiZhi.y;
            sheZhiGuangBiaoWeiZhi(x-1,y);sheZhiYanSe(HUANG_SE);cout<<'<';
            sheZhiGuangBiaoWeiZhi(x+1,y);cout<<'>';
            sheZhiGuangBiaoWeiZhi(x,y-1);cout<<'^';
            sheZhiGuangBiaoWeiZhi(x,y+1);cout<<'v';
            sheZhiYanSe(BAI_SE);
        }
    }

    void faSheXiaoNiao(const ShiLiang2& fangXiang,float liDu){
        if(zaiDanGong){
            suDu=fangXiang*liDu;
            yuanSuDuDaXiao=liDu;
            faShe=true;
            zaiDanGong=false;
            luoDi=false;
            tingZhiJiShiQi=0;
            faSheJiShiQi=0;
            jiNengChuFa=false;
            ziDongJiNengJianChaJiShiQi=0;
            yingYongWuLi=true;
            jiNengJiuXu=false;
            jiNengLengQue=0;
            yongLeJiNeng=false;
        }
    }

    bool jiHuoTeShuJiNeng(){
        if(yongLeJiNeng||jiNengLengQue>0||luoDi)return false;
        yongLeJiNeng=true;
        if(xiaoNiaoLeiXing==0){jiNengLengQue=60;return true;}
        else if(xiaoNiaoLeiXing==1){suDu=suDu*2.5f;jiNengLengQue=40;return true;}
        else if(xiaoNiaoLeiXing==2){suDu.y=8.0f;suDu.x*=0.5f;jiNengLengQue=30;return true;}
        else if(xiaoNiaoLeiXing==3){jiNengLengQue=50;return true;}
        else if(xiaoNiaoLeiXing==4){suDu=ShiLiang2(-suDu.x,suDu.y)*1.5f;jiNengLengQue=45;return true;}
        else if(xiaoNiaoLeiXing==5){jiNengLengQue=35;return true;}
        return false;
    }

    bool nengJiHuoShouDongJiNeng()const{
        return jiNengJiuXu&&jiNengLengQue==0&&!yongLeJiNeng&&!luoDi;
    }
    void shouDaoShangHai(int sh){
        xueLiang-=sh;
        if(xueLiang<=0)jiHuo=false;
    }
    bool shiZaiDanGong()const{return zaiDanGong;}
    bool shiFaShe()const{return faShe;}
    int getLeiXing()const{return xiaoNiaoLeiXing;}
    bool shiJiNengJiuXu()const{return jiNengJiuXu&&jiNengLengQue==0;}
    int getJiNengLengQue()const{return jiNengLengQue;}
    void sheYongLeJiNeng(bool y){yongLeJiNeng=y;}
    bool shiYongLeJiNeng()const{return yongLeJiNeng;}
};

class XiaoZhu:public YouXiDuiXiang{
private:
    int xueLiang;
    int zuiDaXueLiang;
    int dengJi;
    int jiangLi;
    int zhiChengJianChaJiShiQi;
    float wenDingXing;
    int shouJiLengQue;

public:
    XiaoZhu(float x,float y,int dj=1)
        :YouXiDuiXiang(x,y,'P',QIAN_LV),dengJi(dj),jiangLi(50*dj),
          zhiChengJianChaJiShiQi(0),wenDingXing(0.3f),shouJiLengQue(0){
        zuiDaXueLiang=20+dj*15;
        xueLiang=zuiDaXueLiang;
        sheBanJing(1.0f);
        yingYongWuLi=true;
        luoDi=false;

        if(dj>=3)fuHao='Q';
        else if(dj==2)fuHao='P';
        else fuHao='p';

        if(dj==1)yanSe=QIAN_LV;
        else if(dj==2)yanSe=HUANG_SE;
        else if(dj==3)yanSe=QIAN_HONG;
    }

    void gengXin()override{
        YouXiDuiXiang::gengXin();
        if(shouJiLengQue>0)shouJiLengQue--;
        if(shouJiLengQue==0&&luoDi&&suDu.moChang()<0.1f&&weiZhi.y>=DI_MIAN_Y-1){
            yingYongWuLi=false;
        }
        if(zhiChengJianChaJiShiQi++>10)zhiChengJianChaJiShiQi=0;
    }

    void huaZhi()override{
        if(jiHuo&&xueLiang>0){
            int x=(int)weiZhi.x,y=(int)weiZhi.y;
            int xianShiYanSe;
            if(xueLiang>zuiDaXueLiang*0.6)xianShiYanSe=yanSe;
            else if(xueLiang>zuiDaXueLiang*0.3)xianShiYanSe=HUANG_SE;
            else xianShiYanSe=QIAN_HONG;
            sheZhiGuangBiaoWeiZhi(x,y);
            sheZhiYanSe(xianShiYanSe);
            cout<<fuHao;
            sheZhiYanSe(BAI_SE);
        }
    }

    void shouDaoShangHai(int sh){
        xueLiang-=sh;
        if(sh>0&&!yingYongWuLi){
            yingYongWuLi=true;
            luoDi=false;
            wenDing=false;
            shouJiLengQue=20;
            suDu.y=-1.0f;
            suDu.x=(rand()%10-5)*0.4f;
        }
        if(xueLiang<=0){
            jiHuo=false;
            suDu.y=-2.0f;
            suDu.x=(rand()%20-10)*0.6f;
        }
    }

    int getJiangLi()const{return jiangLi;}
    int getXueLiang()const{return xueLiang;}
    int getZuiDaXueLiang()const{return zuiDaXueLiang;}
    float getWenDingXing()const{return wenDingXing;}
    void sheShouJiLengQue(int zhen){shouJiLengQue=zhen;}
    int getShouJiLengQue()const{return shouJiLengQue;}
};

class FangKuai:public YouXiDuiXiang{
private:
    int qiangDu;
    int zuiDaQiangDu;
    char fangKuaiLeiXing;
    int duiDieGaoDu;
    bool yiCuiHui;
    float fanTanXiShu;
    float dingBuY;
    float wenDingXing;

public:
    float shangHaiXiShu;
    FangKuai(float x,float y,char lx='#',int gao=1)
        :YouXiDuiXiang(x,y,lx,ZONG_SE),duiDieGaoDu(gao),yiCuiHui(false),
          dingBuY(y-gao+1),shangHaiXiShu(1.0f),fangKuaiLeiXing(lx){
        sheBanJing(1.0f);
        if(lx=='#'){fuHao='#';yanSe=ZONG_SE;qiangDu=25;wenDingXing=0.6f;fanTanXiShu=0.6f;shangHaiXiShu=1.0f;}
        else if(lx=='%'){fuHao='%';yanSe=AN_HUI;qiangDu=120;wenDingXing=0.9f;fanTanXiShu=0.8f;shangHaiXiShu=0.5f;}
        else if(lx=='+'){fuHao='+';yanSe=QIAN_QING;qiangDu=10;wenDingXing=0.2f;fanTanXiShu=0.3f;shangHaiXiShu=2.0f;}
        else if(lx=='='){fuHao='=';yanSe=QIAN_HUI;qiangDu=200;wenDingXing=1.0f;fanTanXiShu=0.9f;shangHaiXiShu=0.3f;}
        else if(lx=='&'){fuHao='&';yanSe=ZI_SE;qiangDu=40;wenDingXing=0.7f;fanTanXiShu=0.5f;shangHaiXiShu=1.2f;}
        else if(lx=='x'){fuHao='x';yanSe=HONG_SE;qiangDu=80;wenDingXing=0.8f;fanTanXiShu=0.7f;shangHaiXiShu=0.8f;}
        else if(lx=='T'){fuHao='T';yanSe=LV_SE;qiangDu=15;wenDingXing=0.4f;fanTanXiShu=0.4f;shangHaiXiShu=1.5f;}
        else if(lx=='H'){fuHao='H';yanSe=QING_SE;qiangDu=60;wenDingXing=0.75f;fanTanXiShu=0.6f;shangHaiXiShu=0.9f;}
        else if(lx=='B'){fuHao='B';yanSe=QIAN_LAN;qiangDu=35;wenDingXing=0.65f;fanTanXiShu=0.6f;shangHaiXiShu=0.9f;}
        else if(lx=='S'){fuHao='S';yanSe=QIAN_ZI;qiangDu=45;wenDingXing=0.7f;fanTanXiShu=0.7f;shangHaiXiShu=1.1f;}
        else{fuHao='#';yanSe=ZONG_SE;qiangDu=25;wenDingXing=0.6f;fanTanXiShu=0.6f;shangHaiXiShu=1.0f;}

        zuiDaQiangDu=qiangDu*(1+gao*0.3f);
        qiangDu=zuiDaQiangDu;
        if(y>=DI_MIAN_Y-0.5f){luoDi=true;yingYongWuLi=false;wenDing=true;}
        else yingYongWuLi=true;
    }

    void gengXin()override{
        dingBuY=weiZhi.y-duiDieGaoDu+1;
        YouXiDuiXiang::gengXin();
    }

    void huaZhi()override{
        if(jiHuo&&qiangDu>0){
            int x=(int)weiZhi.x;
            int diBuY=(int)weiZhi.y;
            int xianShiYanSe=yanSe;
            if(qiangDu<zuiDaQiangDu*0.3)xianShiYanSe=QIAN_HONG;
            else if(qiangDu<zuiDaQiangDu*0.6)xianShiYanSe=HUANG_SE;
            sheZhiYanSe(xianShiYanSe);
            for(int i=0;i<duiDieGaoDu;i++){
                int y=diBuY-i;
                if(y>=1&&y<PING_MU_GAO-1){
                    sheZhiGuangBiaoWeiZhi(x,y);
                    cout<<fuHao;
                }
            }
            sheZhiYanSe(BAI_SE);
        }
    }

    ShiLiang2 pengZhuangFanYing(const ShiLiang2& suDu)const override{
        ShiLiang2 fan=suDu;
        switch(fangKuaiLeiXing){
            case '%':fan.x=-fan.x*0.9f;fan.y=-fan.y*0.7f;break;
            case '+':fan.x*=0.5f;fan.y*=0.3f;break;
            case '=':fan.x=-fan.x*1.2f;fan.y=-fan.y*0.9f;break;
            case '&':fan.x=-fan.x*0.7f;fan.y=-fan.y*0.5f;break;
            case 'x':fan.x=-fan.x*0.8f;fan.y=-fan.y*0.6f;break;
            default:fan.x=-fan.x*0.6f;fan.y=-fan.y*0.4f;break;
        }
        return fan;
    }

    void shouDaoShangHai(int sh){
        int shiJiSh=(int)(sh*shangHaiXiShu);
        qiangDu-=shiJiSh;
        if(shiJiSh>0&&!yingYongWuLi&&!shiDiMian()){
            yingYongWuLi=true;
            luoDi=false;
            wenDing=false;
            suDu.y=-1.5f*fanTanXiShu;
            suDu.x=(rand()%20-10)*0.5f*fanTanXiShu;
        }
        if(qiangDu<=0){
            jiHuo=false;
            yiCuiHui=true;
            suDu.y=-2.0f*fanTanXiShu;
            suDu.x=(rand()%20-10)*0.8f*fanTanXiShu;
        }
    }

    bool jianCeDingBuPengZhuang(const ShiLiang2& w,float rong=0.5f)const{
        if(!jiHuo)return false;
        float dx=abs(w.x-weiZhi.x);
        float dy=w.y-dingBuY;
        return dx<1.0f&&dy>-rong&&dy<rong;
    }
    bool shiDiMian()const{return weiZhi.y>=DI_MIAN_Y-0.5f;}
    bool jianCeZaiShang(const FangKuai& qiTa)const{
        if(!jiHuo||!qiTa.jiHuo)return false;
        float dx=abs(weiZhi.x-qiTa.weiZhi.x);
        float dy=weiZhi.y-qiTa.dingBuY;
        return dx<1.5f&&dy>-0.2f&&dy<0.5f;
    }
    bool jianCeCeBianZhiCheng(const FangKuai& qiTa)const{
        if(!jiHuo||!qiTa.jiHuo)return false;
        float dx=abs(weiZhi.x-qiTa.weiZhi.x);
        float dy=abs(weiZhi.y-qiTa.weiZhi.y);
        return dx<1.5f&&dy<1.5f;
    }
    float getDingBuY()const{return dingBuY;}
    int getDuiDieGaoDu()const{return duiDieGaoDu;}
    int getQiangDu()const{return qiangDu;}
    bool shiYiCuiHui()const{return yiCuiHui;}
    int getJiangLi()const{
        int jiChu=duiDieGaoDu*10;
        if(fangKuaiLeiXing=='%')return jiChu*2;
        else if(fangKuaiLeiXing=='+')return jiChu/2;
        else if(fangKuaiLeiXing=='=')return jiChu*3;
        else if(fangKuaiLeiXing=='&')return jiChu*1.5;
        else if(fangKuaiLeiXing=='x')return jiChu*1.8;
        else if(fangKuaiLeiXing=='T')return jiChu*0.7;
        else if(fangKuaiLeiXing=='H')return jiChu*1.3;
        else if(fangKuaiLeiXing=='B')return jiChu*1.2;
        else if(fangKuaiLeiXing=='S')return jiChu*1.4;
        else return jiChu;
    }
    bool zhanJuWeiZhi(int x,int y)const{
        if(!jiHuo)return false;
        int jcX=(int)weiZhi.x,jcY=(int)weiZhi.y;
        return x==jcX&&y<=jcY&&y>jcY-duiDieGaoDu;
    }
    bool zhanJuRenYiWeiZhi(int x,int y,int gao)const{
        if(!jiHuo)return false;
        for(int h=0;h<gao;h++)if(zhanJuWeiZhi(x,y-h))return true;
        return false;
    }
    char getLeiXing()const{return fangKuaiLeiXing;}
    bool jianCeDianPengZhuang(const ShiLiang2& d,float rong=0.5f)const{
        if(!jiHuo)return false;
        float dx=abs(d.x-weiZhi.x);
        float db=dingBuY,ds=weiZhi.y;
        return dx<0.5f+rong&&d.y>=db-rong&&d.y<=ds+rong;
    }
    bool jianCeYuanPengZhuang(const ShiLiang2& yx,float bj)const{
        if(!jiHuo)return false;
        float dx=abs(yx.x-weiZhi.x);
        float db=dingBuY,ds=weiZhi.y;
        float jx=max(weiZhi.x-0.5f,min(yx.x,weiZhi.x+0.5f));
        float jy=max(db,min(yx.y,ds));
        float cx=yx.x-jx,cy=yx.y-jy;
        return cx*cx+cy*cy<bj*bj;
    }
    bool chongTu(const FangKuai& qiTa)const{
        if(!jiHuo||!qiTa.jiHuo||getId()==qiTa.getId())return false;
        if(abs(weiZhi.x-qiTa.weiZhi.x)<0.5f){
            float td=dingBuY,ts=weiZhi.y;
            float qd=qiTa.dingBuY,qs=qiTa.weiZhi.y;
            return !(ts<qd||td>qs);
        }
        return false;
    }
    float getWenDingXing()const{return wenDingXing;}
    bool nengZhiCheng()const{return jiHuo&&qiangDu>0&&luoDi&&!yingYongWuLi&&wenDing;}
    bool nengTuoZhuXiaoZhu()const{return jiHuo&&qiangDu>0&&wenDingXing>0.3f&&wenDing;}
    void shiQuZhiCheng(){
        if(!jiHuo)return;
        yingYongWuLi=true;
        luoDi=false;
        wenDing=false;
        if(suDu.moChang()<0.5f){
            suDu.y-=0.3f;
            suDu.x+=(rand()%20-10)*0.1f;
        }
    }
};

class DanGong{
private:
    ShiLiang2 weiZhi;
public:
    DanGong():weiZhi(12,22){}
    void huaZhi(){
        int x=(int)weiZhi.x,y=(int)weiZhi.y;
        sheZhiYanSe(HUANG_SE);
        sheZhiGuangBiaoWeiZhi(x-2,y-1);cout<<"/ ";
        sheZhiGuangBiaoWeiZhi(x+1,y-1);cout<<" \\";
        sheZhiGuangBiaoWeiZhi(x-2,y);cout<<"|  |";
        sheZhiGuangBiaoWeiZhi(x-2,y+1);cout<<"\\_/";
        sheZhiYanSe(BAI_SE);
    }
    ShiLiang2 getWeiZhi()const{return weiZhi;}
};

struct GuanQiaShuJu{
    int guanQiaBianHao;
    int xiaoZhuShu;
    int fangKuaiShu;
    vector<int> xiaoNiaoLeiXing;
    vector<pair<int,int>> xiaoZhuWeiZhi;
    vector<pair<pair<int,int>,pair<char,int>>> fangKuaiShuJu;
    float nanDu;
    string mingCheng;
};

class CunDangShuJu{
private:
    map<string,string> shuJu;
    string wenJianMing;
public:
    CunDangShuJu(string wjm="angry_birds_save.txt"):wenJianMing(wjm){load();}
    void she(string key,string val){shuJu[key]=val;}
    string get(string key,string df=""){
        if(shuJu.count(key))return shuJu[key];
        return df;
    }
    int getInt(string key,int df=0){
        string val=get(key);
        if(!val.empty())return atoi(val.c_str());
        return df;
    }
    bool getBool(string key,bool df=false){
        string val=get(key);
        if(!val.empty())return val=="1";
        return df;
    }
    void save(){
        ofstream f(wenJianMing.c_str());
        if(f.is_open()){
            for(auto& p:shuJu)f<<p.first<<"="<<p.second<<endl;
            f.close();
        }
    }
    void load(){
        ifstream f(wenJianMing.c_str());
        if(f.is_open()){
            string hang;
            while(getline(f,hang)){
                size_t pos=hang.find('=');
                if(pos!=string::npos)shuJu[hang.substr(0,pos)]=hang.substr(pos+1);
            }
            f.close();
        }
    }
    void reset(){shuJu.clear();save();}
};

class FenNuXiaoNiaoYouXi{
private:
    vector<XiaoNiao> xiaoNiaoLie;
    vector<XiaoZhu> xiaoZhuLie;
    vector<FangKuai> fangKuaiLie;
    vector<Dan> danLie;
    vector<GuanQiaShuJu> guanQiaLie;
    DanGong danGong;
    CunDangShuJu cunDang;
    int dangQianGuanQia;
    int fenShu;
    int zongFenShu;
    bool youXiJieShu;
    bool guanQiaWanCheng;
    bool xianShiGuiJi;
    float miaoZhunJiao;
    float miaoZhunLiDu;
    int lianJi;
    float lianJiBeiShu;
    bool xianShiJiaoCheng;

    enum YouXiZhuangTai{
        CAI_DAN,
        GUAN_QIA_XUAN_ZE,
        YOU_XI_ZHONG,
        GUAN_QIA_WAN_CHENG,
        YOU_XI_SHI_BAI,
        JIAO_CHENG
    }youXiZhuangTai;

    vector<vector<char>> pingMuHuanChong;
    vector<vector<int>> yanSeHuanChong;
    struct BaoZha{ShiLiang2 weiZhi;int jiShiQi;int zuiDaJiShi;};
    vector<BaoZha> baoZhaLie;
    vector<vector<int>> weiZhiZhanYong;
    vector<FangKuai> linShiFangKuai;

    struct JianZhuMoBan{
        struct ZhuZi{int dx;int gao;char leiXing;};
        struct XiaoZhuWei{int dx;int dy;};
        vector<ZhuZi> zhuZi;
        vector<XiaoZhuWei> xiaoZhuWei;
    };
    static const JianZhuMoBan jianZhuMoBan[];

    void yingYongBaoZha(ShiLiang2 w,int daXiao,bool heiSe){
        chuangJianBaoZha(w,daXiao);
        for(size_t i=0;i<xiaoZhuLie.size();){
            if(xiaoZhuLie[i].shiJiHuo()&&ShiLiang2::juLi(w,xiaoZhuLie[i].getWeiZhi())<daXiao){
                int sh=heiSe?60:25;
                xiaoZhuLie[i].shouDaoShangHai(sh);
                if(!xiaoZhuLie[i].shiJiHuo()){
                    fenShu+=xiaoZhuLie[i].getJiangLi();
                    qingChuWeiZhiZhanYong((int)xiaoZhuLie[i].getWeiZhi().x,(int)xiaoZhuLie[i].getWeiZhi().y,1);
                }else if(heiSe){
                    ShiLiang2 fx=xiaoZhuLie[i].getWeiZhi()-w;
                    float mo=fx.moChang();
                    if(mo>0.1f)fx=fx/mo*0.15f,xiaoZhuLie[i].sheSuDu(xiaoZhuLie[i].getSuDu()+fx);
                }
                i++;
            }else i++;
        }
        for(size_t i=0;i<fangKuaiLie.size();){
            if(fangKuaiLie[i].shiJiHuo()&&ShiLiang2::juLi(w,fangKuaiLie[i].getWeiZhi())<daXiao){
                int sh=heiSe?80:40;
                fangKuaiLie[i].shouDaoShangHai(sh);
                if(!fangKuaiLie[i].shiJiHuo()){
                    fenShu+=fangKuaiLie[i].getJiangLi();
                    qingChuWeiZhiZhanYong((int)fangKuaiLie[i].getWeiZhi().x,(int)fangKuaiLie[i].getWeiZhi().y,fangKuaiLie[i].getDuiDieGaoDu());
                    dangFangKuaiCuiHui(i);
                }else if(heiSe){
                    ShiLiang2 fx=fangKuaiLie[i].getWeiZhi()-w;
                    float mo=fx.moChang();
                    if(mo>0.1f)fx=fx/mo*0.1f,fangKuaiLie[i].sheSuDu(fangKuaiLie[i].getSuDu()+fx);
                }
                i++;
            }else i++;
        }
    }

    bool weiZhiBeiFangKuaiZhanJu(int x,int y,const vector<FangKuai>& fk)const{
        for(auto& f:fk)if(f.shiJiHuo()&&f.zhanJuWeiZhi(x,y))return true;
        return false;
    }
    bool anQuanXiaoZhuWeiZhi(int x,int y,const vector<FangKuai>& fk)const{
        if(x<1||x>=PING_MU_KUAN-1||y<1||y>=DI_MIAN_Y)return false;
        if(weiZhiBeiFangKuaiZhanJu(x,y,fk))return false;
        if(y==DI_MIAN_Y-1)return true;
        if(y+1>=DI_MIAN_Y)return false;
        for(auto& f:fk)if(f.shiJiHuo()&&f.getDingBuY()==y+1&&abs(f.getWeiZhi().x-x)<0.8f)return true;
        return false;
    }
    bool zhaoDaoYouXiaoXiaoZhuWeiZhi(int& x,int& y,const vector<FangKuai>& fk){
        for(int o=0;o<=6;o++){int ny=y-o;if(ny<1)break;if(anQuanXiaoZhuWeiZhi(x,ny,fk)){y=ny;return true;}}
        for(int dx=-1;dx<=1;dx++){if(dx==0)continue;int nx=x+dx;for(int o=0;o<=6;o++){int ny=y-o;if(ny<1)break;if(anQuanXiaoZhuWeiZhi(nx,ny,fk)){x=nx;y=ny;return true;}}}
        for(int tx=x-2;tx<=x+2;tx++){if(tx<1||tx>=PING_MU_KUAN-1)continue;if(anQuanXiaoZhuWeiZhi(tx,DI_MIAN_Y-1,fk)){x=tx;y=DI_MIAN_Y-1;return true;}}
        return false;
    }
    void tiaoZhengXiaoZhuWeiZhi(GuanQiaShuJu& gq,const vector<FangKuai>& fk){
        vector<pair<int,int>> xinWei;
        for(auto& p:gq.xiaoZhuWeiZhi){
            int x=p.first,y=p.second;
            if(zhaoDaoYouXiaoXiaoZhuWeiZhi(x,y,fk))xinWei.emplace_back(x,y);
            else gq.xiaoZhuShu--;
        }
        gq.xiaoZhuWeiZhi=xinWei;
    }

public:
    FenNuXiaoNiaoYouXi():dangQianGuanQia(1),fenShu(0),zongFenShu(0),youXiJieShu(false),
        guanQiaWanCheng(false),xianShiGuiJi(true),miaoZhunJiao(45.0f),miaoZhunLiDu(8.0f),
        lianJi(0),lianJiBeiShu(1.0f),xianShiJiaoCheng(true),youXiZhuangTai(CAI_DAN){
        srand((unsigned int)time(NULL));
        chuShiHuaPingMuHuanChong();
        chuShiHuaWeiZhiZhanYong();
        loadCunDang();
        shengChengGuanQia();
    }

    void chuShiHuaPingMuHuanChong(){
        pingMuHuanChong.resize(PING_MU_GAO,vector<char>(PING_MU_KUAN,' '));
        yanSeHuanChong.resize(PING_MU_GAO,vector<int>(PING_MU_KUAN,BAI_SE));
    }
    void chuShiHuaWeiZhiZhanYong(){
        weiZhiZhanYong.resize(PING_MU_GAO,vector<int>(PING_MU_KUAN,0));
    }
    void qingKongHuanChong(){
        for(int y=0;y<PING_MU_GAO;y++)for(int x=0;x<PING_MU_KUAN;x++)
            pingMuHuanChong[y][x]=' ',yanSeHuanChong[y][x]=BAI_SE,weiZhiZhanYong[y][x]=0;
    }
    void huaZhiDaoHuanChong(int x,int y,char f,int yse){
        if(x>=0&&x<PING_MU_KUAN&&y>=0&&y<PING_MU_GAO)
            pingMuHuanChong[y][x]=f,yanSeHuanChong[y][x]=yse;
    }
    void huaZhiWenZiDaoHuanChong(int x,int y,string w,int yse){
        for(size_t i=0;i<w.size();i++)if(x+i<PING_MU_KUAN)huaZhiDaoHuanChong(x+i,y,w[i],yse);
    }
    void xianShiHuanChong(){
        sheZhiGuangBiaoWeiZhi(0,0);
        int zuiHouYse=-1;
        for(int y=0;y<PING_MU_GAO;y++){
            for(int x=0;x<PING_MU_KUAN;x++){
                if(yanSeHuanChong[y][x]!=zuiHouYse)sheZhiYanSe(yanSeHuanChong[y][x]),zuiHouYse=yanSeHuanChong[y][x];
                cout<<pingMuHuanChong[y][x];
            }
            if(y<PING_MU_GAO-1)cout<<'\n';
        }
        sheZhiYanSe(BAI_SE);
    }

    bool nengFangFangKuai(int x,int y,int gao,bool linShi=true){
        if(x<1||x>=PING_MU_KUAN-1||y<1||y>=PING_MU_GAO-1)return false;
        if(linShi)for(auto& f:linShiFangKuai)if(f.zhanJuRenYiWeiZhi(x,y,gao))return false;
        else for(auto& f:fangKuaiLie)if(f.shiJiHuo()&&f.zhanJuRenYiWeiZhi(x,y,gao))return false;
        return true;
    }