if (l) rec(0.1,0,0.8,0.1,clr);
clr = Mix(0x000000,clr,0.05);
if (d) rec(0.9,0.1,0.1,0.8,clr);
if (r) rec(0.1,0.9,0.8,0.1,clr);
}
#undef sq
#undef rec
void PaintGrid(double x, double y, int clr, EBlockStyle Style, double th=0.0, double rx=0.0, double ry=0.0, bool u=false, bool d=false, bool l=false, bool r=false) {
PaintTile(SX-x, y-1, clr, 1.0, Style, th, SX-rx+1, ry-1, u, d, l, r);
}
void PaintPiece(const Piece &p, double x, double y, double sz, int clr=-1, EBlockStyle Style=S_Active, int MinSize=4) {
int LX=p.GetLX(); double ss=sz/double(LX);
if (K*double(GetSize())>=8.0) Square(x,y,sz,BoardColor);
if (LX<MinSize) {
x+=0.5*sz*double(MinSize-LX)/double(MinSize); y+=0.5*sz*double(MinSize-LX)/double(MinSize);
ss = sz/double(MinSize);
}
for (int i=0; i<LX; ++i) {
for (int j=0; j<LX; ++j) {
int val = p.GetGrid(LX-i-1,j);
if (!val) continue;
if (clr>=0) val=clr;
PaintTile(x+i*ss, y+j*ss, abs(val), ss, Style);
}
}
}
void GetAccessMap(AccessMap *res, Status *Sta, Piece &p) {
Piece NewP = p;
for (int d=0; d<4; ++d) {
NewP.SetDir(d);
pair<int,int> Anch = NewP.GetAnchor();
for (int i=1; i<=Sta->LX; ++i) {
for (int j=1; j<=Sta->LY; ++j) res->B[d][i][j]=Sta->CheckPlace(NewP,i-Anch.first,j-Anch.second);
}
}
}
struct PosTuple {
int d, x, y;
bool operator <(PosTuple b) const {
if (d!=b.d) return d<b.d;
if (x!=b.x) return x<b.x;
return y<b.y;
}
bool operator ==(PosTuple b) const {
return ((d==b.d)&&(x==b.x)&&(y==b.y));
}
};
vector<pair<PosTuple,bool> > GetLocations(AccessMap *Map, AccessMap *Tmp, Piece p, int Height, int Inc, bool TryFinalRotate=false, bool Clutch=false) {
int LX=Map->LX, LY=Map->LY;
pair<int,int> Anch[4]; Piece NewP=p;
for (int i=0; i<4; ++i) {
NewP.SetDir(i); Anch[i]=NewP.GetAnchor();
}
vector<pair<PosTuple,bool> > res;
vector<PosTuple> SpinPos;
pair<int,int> Place = SpawnPlace(p);
int d=p.GetDir(), x=Place.first+Anch[d].first+Inc, y=Place.second+Anch[d].second;
if (!Map->Query(d,x,y)) {
if (!Clutch) return res;
bool f = false;
for (int i=1; i<=LX-SX+6; ++i) {
++x; ++Place.first;
if (Map->Query(d,x,y)) {
f=true; break;
}
}
if (!f) return res;
}
int HeightLim = Height+2;
for (int d=0; d<4; ++d) {
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if (i<=HeightLim) Tmp->B[d][i][j]=Map->B[d][i][j];
else Tmp->B[d][i][j]=false;
}
}
}
x = min(x,HeightLim);
Tmp->B[d][x][y]=false; stack<PosTuple> stk; stk.push((PosTuple){d,x,y});
vector<pair<int,int> > Kick[4][4];
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
Kick[i][j] = GetKickTable(i,j,p.GetRealName(),RotateSystem);
for (pair<int,int> &o : Kick[i][j]) {
swap(o.first, o.second);
o.first += Anch[j].first-Anch[i].first;
o.second += Anch[j].second-Anch[i].second;
}
}
}
while (!stk.empty()) {
PosTuple o=stk.top(); stk.pop();
d=o.d; x=o.x; y=o.y;
if ((SideGravity)&&(DropDelay)) {
if (Map->Query(d,x,y-1)) {
if (Tmp->Query(d,x,y-1)) {
Tmp->B[d][x][y-1]=false; stk.push((PosTuple){d,x,y-1});
}
continue;
}
}
if (Tmp->Query(d,x-1,y)) {
Tmp->B[d][x-1][y]=false; stk.push((PosTuple){d,x-1,y});
}
else if (!Map->Query(d,x-1,y)) res.push_back(make_pair((PosTuple){d,x-Anch[d].first,y-Anch[d].second},false));
if ((!DropDelay)&&(Map->Query(d,x-1,y))) continue;
if ((UseMove)&&(Tmp->Query(d,x,y-1))) {
Tmp->B[d][x][y-1]=false; stk.push((PosTuple){d,x,y-1});
}
if ((UseMove)&&(Tmp->Query(d,x,y+1))) {
Tmp->B[d][x][y+1]=false; stk.push((PosTuple){d,x,y+1});
}
for (int nd=0; nd<4; ++nd) {
if (nd==d) continue;
int dd = ((nd-d+4)&3);
bool f = true;
if (dd==2) f=UseHalf;
else f=((Use2Rot)||((UseRotate)&&(dd==DefaultRot)));
if (!f) continue;
int nx=-1, ny=-1;
for (pair<int,int> o : Kick[d][nd]) {
if (Map->Query(nd,x+o.first,y+o.second)) {
nx=x+o.first; ny=y+o.second; break;
}
}
if (nx>=0) {
if (Tmp->Query(nd,nx,ny)) {
if ((TryFinalRotate)&&(dd!=2)) SpinPos.push_back((PosTuple){nd,nx-Anch[nd].first,ny-Anch[nd].second});
Tmp->B[nd][nx][ny]=false; stk.push((PosTuple){nd,nx,ny});
}
}
}
}
if (!TryFinalRotate) return res;
sort(res.begin(), res.end());
sort(SpinPos.begin(), SpinPos.end());
int pp = 0;
for (pair<PosTuple,bool> &o : res) {
while ((pp<SpinPos.size())&&(SpinPos[pp]<o.first)) ++pp;
if ((pp<SpinPos.size())&&(SpinPos[pp]==o.first)) o.second=true;
}
return res;
}
int VecDfs(vector<vector<char> > &vec, int x, int y) {
if (vec[x][y]) return 0;
vec[x][y] = 1;
return 1+VecDfs(vec,x+1,y)+VecDfs(vec,x-1,y)+VecDfs(vec,x,y+1)+VecDfs(vec,x,y-1);
}
//#warning Board::Eval
int PreHeight;
int DHeight(bool **D, int j, int wh) {
if ((j<1)||(j>LY)) return LX;
for (int i=wh+1; i<=LX; ++i) {
if (!D[i][j]) return i;
}
return LX+1;
}
ll Eval(Status *Sta, Piece &_p, PosTuple o, bool Spin, int d, int x, int y, bool Spinable) {
int LX=Sta->LX, LY=Sta->LY;
bool **D = Sta->B;
int Lines=0, pp=0;
int Height=0, PieceHeight=0, LeftMost=LY, RightMost=0, Edge=LY;
Piece p=_p; p.SetDir(o.d);
int PLX = p.GetLX();
vector<int> Fill(LX+2,0), Upper(LY+2,0);
bool Use90=Spinable; Spinable|=Spin;
bool TSp=false, TFull=false;
int CenterY = 0;
if (((BotType==1)||(BotType==3)||(BotType==8))&&((Spin)||(Spinable))&&(IsSpinBonus(_p.GetName()))) {
int px=x+1, py=y+1;
int t1=0, t2=0;
int fi=0, fj=0;
if (!d) fi=1;
else if (d==1) fj=1;
else if (d==2) fi=-1;
else fj=-1;
fi=-fi; fj=-fj;
CenterY = py;
for (int ii=-1; ii<=1; ii+=2) {
for (int jj=-1; jj<=1; jj+=2) {
int nx=px+ii, ny=py+jj;
if (Sta->CheckGrid(nx,ny)) {
++t1;
if ((ii!=fi)&&(jj!=fj)) ++t2;
}
}
}
if (t1>2) TSp=true;
if ((t1>2)&&(t2>1)) TFull=true;
if (_p.GetName()!="T") TFull=TSp=Spin;
}
if ((SpinRule==SR_Guildline)&&(!Mod8)&&(!IsSpinBonus(_p.GetName()))&&(Lines<4)) Spin=false;
if ((SpinRule==SR_Guildline)&&(!Mod8)) {
if ((!TSp)&&(Lines<4)) Spin=false;
}
bool CalcAllMini = ((SpinRule==SR_Default)&&(Gen.Pool.size()<=10)&&(!Mod8)&&((BotType==1)||(BotType==3)));
bool AllMini=false, ex1=false, ex2=false, sw=false, ew=false; int eu=0;
for (int i=0; i<PLX; ++i) {
for (int j=0; j<PLX; ++j) {
int x=o.x+i, y=o.y+j;
if ((x<1)||(y<1)||(x>LX)||(y>LY)) continue;
if (!p.GetGrid(i,j)) {
if (!CalcAllMini) continue;
int ad = 0;
if ((i>0)&&(p.GetGrid(i-1,j))) ++ad;
if ((i+1<PLX)&&(p.GetGrid(i+1,j))) ++ad;
if ((j>0)&&(p.GetGrid(i,j-1))) ++ad;
if ((j+1<PLX)&&(p.GetGrid(i,j+1))) ++ad;
if (ad>=2) {
ew=true; if (!D[x][y]) sw=true;
}
continue;
}
++Fill[x];
PieceHeight = max(PieceHeight,x);
LeftMost = min(LeftMost,y);
RightMost = max(RightMost,y);
Edge = min(Edge,min(y-1,LY-y));
if (!CalcAllMini) continue;
int ex = 0;
if ((x==1)||(D[x-1][y])) ++ex;
if ((x==LX)||(D[x+1][y])) {
++ex;
if ((i+1==PLX)||(!p.GetGrid(i+1,j))) ++eu;
}
if ((y==1)||(D[x][y-1])) ++ex;
if ((y==LY)||(D[x][y+1])) ++ex;
if (ex<=1) ex1=true;
if (ex<=2) ex2=true;
}
}
if (CalcAllMini) {
if (IsOType(_p.GetName())) AllMini=(eu<2);
else AllMini=((!Use90)||(ex1)||((ex2)&&((sw)||(!ew))));
}
int FillCnt=0, FillCol=0;
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if (D[i][j]) {
if (!Upper[j]) {
Upper[j]=true; ++FillCol;
}
}
}
if ((Fill[i])&&(FillCol==LY)) ++FillCnt;
}
/*int LQH=0, RQH=0;
if ((BotType==6)||(BotType==7)) {
int acc = 0;
for (int i=1; i<=LX; ++i) {
int cur = 0;
for (int j=2; j<=LY; ++j) {
if (D[i][j]) break;
else ++cur;
}
if (cur>=LY-1) break;
if (cur) {
acc+=cur; if (acc>3) break;
}
else {
cur=0; LQH=i;
}
}
for (int i=1; i<=LX; ++i) {
int cur = 0;
for (int j=LY-1; j; --j) {
if (D[i][j]) break;
else ++cur;
}
if (cur>=LY-1) break;
if (cur) {
acc+=cur; if (acc>3) break;
}
else {
cur=0; RQH=i;
}
}
}*/
int Ero = 0;
for (int i=1; i<=LX; ++i) {
bool f = true;
for (int j=1; j<=LY; ++j) {
if (!D[i][j]) {
f=false; break;
}
}
for (int x : StaticLines) {
if (i==x) f=false;
}
if (f) {
if (Fill[i]) ++Lines;
Ero += Fill[i];
if (GravityType==GV_None) {
++pp; for (int j=1; j<=LY; ++j) D[pp][j]=false;
}
}
else {
++pp;
if (i!=pp) {
for (int j=1; j<=LY; ++j) {
D[pp][j]=D[i][j]; D[i][j]=false;
}
}
}
}
Sta->Clutch = false;
if ((ClutchRule==CLR_Default)&&(Lines)) Sta->Clutch=true;
if (ClutchRule==CLR_Always) Sta->Clutch=true;
if (Lines) ++Sta->Combo;
else Sta->Combo=0;
ll res = 0LL;
ll ares = 0LL;
bool SetSpin = (((BotType==1)||(BotType==3)||(BotType==6)||(BotType==7)||(BotType==8))&&(SpinMode));
for (int i=0; i<=LX+1; ++i) D[i][0]=D[i][LY+1]=true;
for (int i=0; i<=LY+1; ++i) D[0][i]=D[LX+1][i]=true;
int BegHeight=Height; Height=0;
bool qd = ((SetSpin)&&((BotType==6)||(BotType==7)));
int WellCol = -1;
if ((Sta->LastClearType.second>0)&&(Sta->LastClearType.second<4)&&(Height>6)) {
if (BotType==9) qd=false;
else if (qd) WellCol=-1;
}
int _wc = -1;
int _wh = 0;
if ((qd)||((SpinRule==SR_Guildline)&&(!Mod8)&&((BotType==1)||(BotType==3)))) {
int mn = LX+1;
if (qd) {
for (int j=LY; j; --j) {
if ((j>=2)&&(j<=LY-1)) continue;
int p = 0;
for (int i=LX; i; --i) {
if (D[i][j]) {
p=i; break;
}
}
if (p<mn) {
mn=p; WellCol=j;
}
}
for (int j=LY; j; --j) {
if ((j==1)||(j==LY)) continue;
int p = 0;
for (int i=LX; i; --i) {
if (D[i][j]) {
p=i; break;
}
}
if (p<mn) {
mn=p; WellCol=j;
}
}
}
else {
for (int j=LY-3; j>=3; --j) {
int p = 0;
for (int i=LX; i; --i) {
if (D[i][j]) {
p=i; break;
}
}
if (p<mn) {
mn=p; WellCol=j;
}
}
for (int j=LY; j>=1; --j) {
if ((j!=1)&&(j!=LY)) continue;
int p = 0;
for (int i=LX; i; --i) {
if (D[i][j]) {
p=i; break;
}
}
if (p<mn) {
mn=p; WellCol=j;
}
}
for (int j=LY; j>=1; --j) {
if ((j!=2)&&(j!=LY-1)) continue;
int p = 0;
for (int i=LX; i; --i) {
if (D[i][j]) {
p=i; break;
}
}
if (p<mn) {
mn=p; WellCol=j;
}
}
_wc=WellCol; _wh=mn;
}
if (mn+10>SX) WellCol=-1;
}
if ((BotType==6)||(BotType==7)) {
if ((WellCol>=2)&&(WellCol<=LY-1)) WellCol=-1;
}
if ((Sta->LastClearType.second>0)&&(Sta->LastClearType.second<4)&&(Height>10)) {
if ((BotType==6)||(BotType==7)) WellCol=-1;
}
if ((BotType==9)&&(SpinMode)) {
int mn = LX+1;
for (int j=LY; j; --j) {
if ((j>=2)&&(j<=LY-1)) continue;
int p = 0;
for (int i=LX; i; --i) {
if (D[i][j]) {
p=i; break;
}
}
if (p<mn) {
mn=p; WellCol=j;
}
}
for (int j=LY; j; --j) {
if ((j==1)||(j==LY)) continue;
int p = 0;
for (int i=LX; i; --i) {
if (D[i][j]) {
p=i; break;
}
}
if (p<mn) {
mn=p; WellCol=j;
}
}
if (mn>=SX/2) WellCol=-1;
if ((WellCol>=2)&&(WellCol<=LY-1)) WellCol=-1;
if (WellCol==-1) res-=30000;
}
if ((qd)&&(WellCol==-1)) res-=30000;
/*if ((BotType==6)||(BotType==7)) {
if (SpinMode) res+=(LX-Height)*10;
}*/
if ((SpinRule==SR_Guildline)&&(!Mod8)&&((BotType==1)||(BotType==3))) {
WellCol = _wc;
if (SetSpin) {
if ((_wc==2)||(_wc==LY-1)) res-=200000;
if ((_wc==1)||(_wc==LY)) {
res-=100000; _wc=-1;
}
}
else WellCol=_wc=-1;
}
else _wc=-1;
//if (WellCol!=-1) printf("!%d\n",WellCol);
for (int i=1; i<=LX; ++i) {
int fc = 0;
for (int j=1; j<=LY; ++j) {
if (D[i][j]) ++fc;
}
int WellCnt = 0;
for (int j=1; j<=LY; ++j) {
if (D[i][j]) {
Height=max(Height,i); continue;
}
if (D[i+1][j]) {
if (GravityType==GV_None) ;
else if (BotType==5) {
if (((j<=2)||(D[i][j-1])||(D[i+1][j-1]))&&((j>=LY-1)||(D[i][j+1])||(D[i+1][j+1])))
res-=5LL;
else --res;
}
else if (BotType==9) res-=5LL;
else if (qd) res-=20LL;
else if ((!SetSpin)||(qd)) res-=5LL;
else if ((SpinRule==SR_Guildline)&&(!Mod8)) {
if ((((j<=2)||(D[i][j-1])||(D[i+1][j-1]))&&((j>=LY-1)||(D[i][j+1])||(D[i+1][j+1])))||((j==1)||(j==LY))) res-=50LL;
else res-=10LL;
}
else if ((((j<=2)||(D[i][j-1])||(D[i+1][j-1]))&&((j>=LY-1)||(D[i][j+1])||(D[i+1][j+1])))||((j==1)||(j==LY)))
res-=10LL;
else res+=0;
}
if ((D[i-1][j])||(i==1)) --res;
if ((D[i][j-1])||(j==1)||(j-1==WellCol)) --res;
if ((D[i][j+1])||(j==LY)||(j+1==WellCol)) --res;
if (((D[i][j-1])||(j==1)||(j-1==WellCol))&&((D[i][j+1])||(j==LY)||(j+1==WellCol))) {
if (_wc>0) {
if (j==_wc) ;
else if (!D[i+1][j]) ;
else if (abs(j-_wc)>1) res-=15;
else if (D[i][max(1,min(LY,_wc+_wc-j))]) res-=30;
else if ((!D[i-1][j])||(!D[i-1][max(1,min(LY,_wc+_wc-j))])) res-=30;
else if ((i+2<=LX)&&((D[i+2][j])&&(D[i+2][max(1,min(LY,_wc+_wc-j))]))) res-=30;
}
if (BotType==9) {
if (j!=WellCol) --res;
}
else if (((!qd)&&(_wc<0))||(j!=WellCol)) {
--res;
}
else if (fc>=LY-1) res+=2;
}
if ((_wc>0)&&((D[i+1][j])&&(D[i][j-1])&&(D[i][j+1]))&&(abs(i-_wc)>1)) res-=10;
}
}
if ((_wc>1)&&(_wc<LY)) {
int Base = 0;
for (int i=1; i<=LX; ++i) {
if ((D[i][_wc-1])&&(D[i][_wc+1])) Base=i;
}
int hl=0, hr=0;
while ((Base+hl+1<=LX)&&(D[Base+hl+1][_wc-1])) ++hl;
while ((Base+hr+1<=LX)&&(D[Base+hr+1][_wc+1])) ++hr;
int del = abs(hl-hr);
res -= ((del==1)?3:min(5,del))*2;
res -= Height*10;
}
if ((!SetSpin)&&((BotType==1)||(BotType==2)||(BotType==3)||(BotType==4))&&(PlayerCount>1)) ares-=Height*500;
if ((GetT)&&(SetSpin)&&((BotType==1)||(BotType==3))) {
int c1=0, c0=0;
int mul = 1;
int pp=0, ph=0;
for (int j=2; j<LY; ++j) {
for (int i=LX-1; i>=2; --i) {
if (D[i][j]) break;
if ((D[i][j])||(D[i-1][j])||(D[i+1][j])||(D[i][j-1])||(D[i][j+1])) continue;
if ((!D[i-1][j-1])||(!D[i-1][j+1])) continue;
int k = int(D[i+1][j-1])+int(D[i+1][j+1]);
if (j==_wc) mul=6;
if ((j!=_wc)&&(_wc>0)) continue;
if (k==1) {
++c1;
if (!pp) {
if (D[i+1][j-1]) pp=j-1;
if (D[i+1][j-1]) pp=j+1;
ph = i+1;
}
}
if (!k) {
if (((D[i][j-2])||(j==2))&&((D[i][j+2])||(j==LY-1))) ++c0;
}
}
}
if ((pp)&&(_wc>0)) {
int d = 1;
while ((ph+d<=LX)&&(D[ph+d][pp])) ++d;
if (d==1) ++res;
if (d>2) res-=2*(d-2);
}
if (c1) res+=5*mul;
else if (c0) res+=1*mul;
/*int c1=0, c0=0;
for (int j=2; j<=LY; ++j) {
for (int i=LX-1; i>=2; --i) {
if (D[i][j]) continue;
if ((D[i-1][j])||(D[i][j-1])||(D[i-1][j-1])) continue;
if ((j>2)&&((!D[i][j-2])&&(!D[i-1][j-2]))) continue;
if ((j<LY)&&((!D[i][j+1])&&(!D[i-1][j+1]))) continue;
if ((i>2)&&((!D[i-2][j])&&(!D[i-2][j-1]))) continue;
if (((j>2)&&(!D[i][j-2]))&&((j<LY)&&(!D[i-1][j+1]))) continue;
if (((j>2)&&(!D[i-1][j-2]))&&((j<LY)&&(!D[i][j+1]))) continue;
int k = int(D[i+1][j])+int(D[i+1][j-1]);
if (k) ++c1;
if (!k) {
if (((D[i][j-2])||(j==2))&&((D[i][j+1])||(j==LY))) ++c0;
}
}
}
if (c1) res+=5;
else if (c0) res+=1;*/
}
bool AllClear = (Height<=SolidHeight);
if ((BotType==6)||(BotType==7)) AllClear=false;
if (SetSpin) {
if ((AllClearRule!=AR_IO)&&(AllClearRule!=AR_Default)&&(AllClearRule!=AR_QP)&&(AllClearRule!=AR_Techmino)
&&(B2BRule!=BR_None)&&(B2BRule!=BR_Guildline)&&(B2BRule!=BR_Techmino)) AllClear=false;
}
Sta->LineAfterPC += Lines;
if (AllClear) Sta->LineAfterPC=0;
if ((Mod8)&&((Lines)||(Spin))) {
pair<string,int> NewClearType = make_pair("",Lines);
if (Spin) NewClearType.first=_p.GetRealName();
if (Mod8==2) {
if (Spin) NewClearType.first="X";
else NewClearType.second=0;
}
if (!Lines) NewClearType.second=-1;
if (NewClearType==Sta->LastClearType) ares-=10000000000LL;
Sta->LastClearType = NewClearType;
}
bool sth = false;
if ((Lines)&&(sth)) {
if (((Lines!=1)||((!Spin)&&((!Spinable)||(!TSp))))) ares-=1000000000LL;
else if ((_f)&&(Lines<4)&&(!Spin)&&(!TSp)) ares-=1000000000LL;
else ares+=10000LL;
}
if (BotType==5) {
int Parity=0, CParity=0;
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if (D[i][j]) {
if (j&1) ++CParity;
else --CParity;
if ((i+j)&1) ++Parity;
else --Parity;
}
}
}
Parity=abs(Parity); CParity=abs(CParity);
//res -= CParity;
int Goal = 4;
if (Height+Sta->LineAfterPC>Goal) ares-=1000000000LL;
else {
int h = min(LX,Goal-Sta->LineAfterPC);
for (int i=1; i<=LY; ++i) {
if (!D[h][i]) --res;
}
vector<vector<char> > G(h+2,vector<char>(LY+2,0));
for (int i=0; i<=h+1; ++i) G[i][0]=G[i][LY+1]=1;
for (int i=0; i<=LY+1; ++i) G[0][i]=G[h+1][i]=1;
for (int i=1; i<=h; ++i) {
for (int j=1; j<=LY; ++j) G[i][j]=D[i][j];
}
for (int i=1; i<=h; ++i) {
for (int j=1; j<=LY; ++j) {
if (!G[i][j]) {
int val = VecDfs(G,i,j);
if (val&1) {
if ((i>=h-1)||(val==1)) res-=5000LL;
else res-=50LL;
}
else if (val&3) {
if ((i>=h-1)||(val==2)) res-=10LL;
else res-=5LL;
}
}
}
}
}
}
res -= Height;
int RotDis=((DefaultRot-o.d+4)&3); if (RotDis==3) RotDis=1;
ares += Lines*Ero*2000LL;
//if (!IsSpinBonus(p.GetName())) Spin=0; Spin|=TSp;
int _Spin = Spin;
if ((!Mod8)&&((SpinRule==SR_AllMini)||(BotType==8)||(Mod2==2))) Spin|=TSp;
//if ((!Mod8)&&((CenterY==1)||(CenterY==LY))) Spin|=TSp;
if (qd) Spin=0;
if ((_f)&&(TQPScore<=1100000)&&(TFull)) Spin=0;
if ((_f)&&(AllClear)) Spin=0;
if ((Lines)&&((BotType==1)||(BotType==3)||(BotType==6)||(BotType==7)||(BotType==8))) {
int SpinBonus = ((!AllMini)?5000:1000);
if (GetT) SpinBonus=(TFull)?10000:(((TSp)&&(_Spin))?5000:500);
if (Lines>3) SpinBonus=max(SpinBonus,5000);
if (AllClear) SpinBonus=max(SpinBonus,10000);
if ((_f)&&(TFull)) SpinBonus=0;
if ((_f)&&(Lines==1)) SpinBonus*=5;
if ((_f)&&(TQPScore<=1100000)&&(Lines>1)&&(Lines<4)) SpinBonus=-5000;
if (SetSpin) {
bool CurB2B = (((Lines>3)&&(Mod8<2))||(Spin));
if ((AllClear)&&(!_f)&&((AllClearRule==AR_Default)||(AllClearRule==AR_IO)
||(AllClearRule==AR_QP)||(AllClearRule==AR_Techmino))) CurB2B=true;
if ((!QPBlighted)&&(Mod6==2)) CurB2B=true;
if ((Spinable)&&(TSp)&&(sth)) CurB2B=true;
if (CurB2B) {
//if ((BotType==1)&&(TFull)) SpinBonus*=10;
int l = Lines+2;
//if (GetT) l=((TFull)||(Lines>=4))?Lines+2:2;
if (_f) l=2;
if ((sth)||(_f)||(Gen.Pool.size()>=10)||(ModM)||((GetT)&&(!TSp))) ares+=ll(SpinBonus)*l;
else ares+=ll(SpinBonus)*(4+max(0,Sta->Combo-1))/4*l;
}
else ares-=max(0LL,1000000LL*(SX-PreHeight)/SX);
}
else if (((Lines>3)||(Spin))&&(Height+8<=SX)) {
SpinBonus /= 2;
if ((sth)||(_f)||(Gen.Pool.size()>=10)||(ModM)||((GetT)&&(!TSp))) ares+=ll(SpinBonus)*Lines;
else ares+=ll(SpinBonus)*(4+max(0,Sta->Combo-1))/4*Lines;
}
}
if ((SpinMode)&&(GetT)&&(IsSpinBonus(_p.GetName()))&&((!Lines)||(!TFull))) {
ares -= 300LL;
if (_wc>0) {
if (_wc-1>LY-_wc) {
if (y>_wc) ares-=100LL;
}
if (LY-_wc>_wc-1) {
if (y<_wc) ares-=100LL;
}
}
}
if (((BotType==1)||(BotType==3))&&((!ModM)&&(Gen.Pool.size()<10))) ares+=3000LL*ll(max(0,min(4,Sta->Combo-1)));
//if ((_wc>0)&&((!Lines)||(!TSp))&&(IsSpinBonus(_p.GetName()))) ares-=500LL;
//if ((GetT)&&((!Lines)||(!TFull))&&(IsSpinBonus(p.GetName()))&&(SetSpin)) ares-=100LL;
if ((Mod8==2)&&((BotType==1)||(BotType==3)||(BotType==8))) {
if (SetSpin) {
if ((Spin)&&(!Lines)) ares+=5000LL;
}
}
if ((BotType==9)&&(Lines)&&(SpinMode)&&(WellCol>0)) {
if ((Combo)&&(SX-PreHeight<10)) ;
else if (FillCnt<4) res-=50;
}
if ((Lines)&&(!_f)) {
if (AllClear) ares+=(SetSpin)?5000LL:100000LL;
}
res = res*2000LL;
if ((SetSpin)&&(!qd)&&(BotType!=6)&&(BotType!=7)&&((Height+10<=SX)||(PlayerCount<2))) {
int hd=2, tot=0, tot4=0;
for (Piece &p : Gen.Pool) {
++tot; if (p.GetLX()>=4) ++tot4;
}
if (tot4*3>=tot) hd=2;
if (tot4*3>=tot*2) hd=8;
for (int i=Height; i>=1; --i) {
if (D[i][1]) {
if ((i>=Height-hd)&&((i==1)||(D[i-1][1]))) {
res += 2000LL;
if (D[i][2]) res+=1000L;
}
}
//else if (D[i+1][1]) res-=2000LL;
}
for (int i=Height; i>=1; --i) {
if (D[i][LY]) {
if ((i>=Height-hd)&&((i==1)||(D[i-1][LY]))) {
res += 2000LL;
if (D[i][LY-1]) res+=1000L;
}
}
//else if (D[i+1][LY]) res-=2000LL;
}
/*for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
int ed = (LY>>1)-min(j-1,LY-j-1);
if (D[i][j]) res-=((LY>>1)*(LY>>1)-ed*ed)*10LL;
}
}*/
}
if ((SetSpin)&&(!qd)&&(BotType!=6)&&(BotType!=7)&&(LY>=6)) {
int cnt = 0;
for (int i=1; i+2<=LX; ++i) {
for (int j=1; j<LY; ++j) {
if ((!D[i][j])&&(!D[i][j+1])
&&(!D[i+1][j])&&(!D[i+1][j+1])&&(D[i+1][j-1])&&(D[i+1][j+2])
&&((j==1)||(j==LY-1)||((!D[i+2][j])&&(!D[i+2][j+1])&&(D[i+2][j-1]&&D[i+2][j+2])))) ++cnt;
}
}
if (cnt) res-=2000LL*cnt;
}
if (!BotType) res-=Edge*100LL+10LL*ll(LeftMost+RightMost<=LY+LY)+ll(RotDis);
Sta->AccEval += ares;
for (int i=0; i<=LX+1; ++i) D[i][0]=D[i][LY+1]=false;
for (int i=0; i<=LY+1; ++i) D[0][i]=D[LX+1][i]=false;
return res;
}
static vector<pair<int,int> > TmpKick[4][4];
vector<Action> FinalSearch(AccessMap *Map, AccessMap *Tmp, int d, int x, int y, int gd, int gx, int gy, bool TryMini=false, bool HalfSame=false, bool Clutch=false) {
int LX=Map->LX, LY=Map->LY;
if ((BotType!=1)&&(BotType!=3)&&(BotType!=8)) TryMini=false;
if (!Map->Query(d,x,y)) {
if (!Clutch) return {A_HardDrop};
bool f = false;
for (int i=1; i<=LX-SX+6; ++i) {
++x;
if (Map->Query(d,x,y)) {
f=true; break;
}
}
if (!f) return {A_HardDrop};
}
Tmp->B[d][x][y] = false;
queue<PosTuple> qu;
queue<vector<Action> > ql;
qu.push((PosTuple){d,x,y}); ql.push(vector<Action>());
vector<Action> TmpRes = {A_HardDrop};
while (!qu.empty()) {
PosTuple o=qu.front(); qu.pop();
vector<Action> lst=ql.front(); ql.pop();
d=o.d; x=o.x; y=o.y;
if ((d==gd)&&(x==gx)&&(y==gy)) {
if (!TryMini) {
lst.push_back(A_HardDrop); return lst;
}
TmpRes=lst; TmpRes.push_back(A_HardDrop);
}
if ((SideGravity)&&(DropDelay)) {
if (Map->Query(d,x,y-1)) {
if (Tmp->Query(d,x,y-1)) {
lst.push_back(A_Left);
Tmp->B[d][x][y-1]=false; qu.push((PosTuple){d,x,y-1});
ql.push(lst); lst.pop_back();
}
continue;
}
}
if (Tmp->Query(d,x-1,y)) {
lst.push_back(A_SoftDrop);
Tmp->B[d][x-1][y]=false; qu.push((PosTuple){d,x-1,y});
ql.push(lst); lst.pop_back();
}
if ((!DropDelay)&&(Map->Query(d,x-1,y))) continue;
for (int nd=0; nd<4; ++nd) {
if (nd==d) continue;
bool f = true;
int dd = ((nd-d+4)&3);
if (dd==2) f=UseHalf;
else f=((Use2Rot)||((UseRotate)&&(dd==DefaultRot)));
if (!f) continue;
int nx=-1, ny=-1;
for (pair<int,int> o : TmpKick[d][nd]) {
if (Map->Query(nd,x+o.first,y+o.second)) {
nx=x+o.first; ny=y+o.second; break;
}
}
if (nx>=0) {
Action Act = A_Half;
if (((d+1)&3)==nd) Act=A_CW;
if (((d+3)&3)==nd) Act=A_CCW;
if ((TryMini)&&(Act!=A_Half)&&(Map->Query(nd,nx,ny))) {
if (((nd==gd)||((HalfSame)&&(nd==(gd^2))))&&(nx==gx)&&(ny==gy)) {
lst.push_back(Act); lst.push_back(A_HardDrop); return lst;
}
}
if (Tmp->Query(nd,nx,ny)) {
lst.push_back(Act);
Tmp->B[nd][nx][ny]=false; qu.push((PosTuple){nd,nx,ny});
ql.push(lst); lst.pop_back();
}
}
}
if ((UseMove)&&(Tmp->Query(d,x,y+1))) {
lst.push_back(A_Right);
Tmp->B[d][x][y+1]=false; qu.push((PosTuple){d,x,y+1});
ql.push(lst); lst.pop_back();
}
if ((UseMove)&&(Tmp->Query(d,x,y-1))) {
lst.push_back(A_Left);
Tmp->B[d][x][y-1]=false; qu.push((PosTuple){d,x,y-1});
ql.push(lst); lst.pop_back();
}
/*int gg = 1;
while (Map->Query(d,x-gg,y)) ++gg;
--gg;
if ((gg)&&(Tmp->Query(d,x-gg,y))) {
lst.push_back(A_SonicDrop);
Tmp->B[d][x-1][y]=false; qu.push((PosTuple){d,x-gg,y});
ql.push(lst); lst.pop_back();
}*/
}
return TmpRes;
}
//#warning Board::SearchNext
vector<Status*> CurLayer, Recycle;
int SearchDepth=1, Keep=1;
bool IgnoreAfterHold=true, GetT;
AccessMap *Map, *Tmp; Status *Current;
Instruction FinalInst, FinalStepInst;
int BeginInc;
vector<int> StaticLines; int SolidHeight=0;
int GetSearchSeg() {
if ((!BotType)||(BotType==8)||(BotType==9)) return 1;
if ((BotType==1)||(BotType==2)||(BotType==6)) return 9;
if ((BotType==3)||(BotType==4)||(BotType==7)) return 14;
if (BotType==5) return 12;
return 1;
}
bool _f = false;
int SameInstLim = 0;
bool SearchBegin() {
BotType = ActType;
TgD=-1; TgX=TgY=0;
if (ActType==5) {
BotType = 0;
if (AliveCount<=5) BotType=2;
}
if (PlayerCount>1) {
if (ActType==8) {
if (AliveCount>=30) BotType=9;
if (AliveCount<=5) BotType=1;
}
if (ActType==9) {
if (AliveCount<=5) BotType=1;
}
}
StaticLines.clear(); SolidHeight=0;
for (int i=1; i<=LX; ++i) {
bool f = true;
for (int j=1; j<=LY; ++j) {
if (!B[i][j]) {
f=false; break;
}
}
for (int j=1; j<=LY; ++j) {
if ((B[i][j])&&(IsUnclearable(B[i][j]))) {
if (f) ++SolidHeight;
StaticLines.push_back(i); break;
}
}
}
BeginInc=HoldPosInc; HoldPosInc=0;
bool HaveT=GetT=false;
if (((BotType==1)||(BotType==3))&&(!Mod8)&&(Mod2<2)&&((SpinRule==SR_Guildline)||(SpinRule==SR_AllMini))) GetT=true;
if (!DropDelay) HaveT=false;
for (Piece o : Pool) {
if (IsSpinBonus(o.GetName())) HaveT=true;
}
if (!HaveT) GetT=false;
if ((Mod9==2&&0)&&(TQPScore<300000)) _f=true;
else _f=false;
if (QPLevTime>=30000LL&&TQPScore>=150000) _f=false;
if (QPLevTime>=45000LL&&TQPScore>=50000) _f=false;
if (_f) GetT=false;
if (Gen.Pool.size()>=20) GetT=false;
SearchDepth=1, Keep=1;
IgnoreAfterHold = true;
CurLayer.clear(); SameInstLim=0;
if (!BotType) {
SearchDepth=1; Keep=1;
}
else if (BotType==1) {
SearchDepth=7; Keep=((HoldType)&&(HoldLen))?15:20;
if (ModP) Keep=20;
if ((BoardID<2)&&(SpinRule==SR_Guildline)) Keep=20;
//if ((ModP)&&(!BoardID)) Keep=100;
IgnoreAfterHold = false;
}
else if (BotType==2) {
SearchDepth=7; Keep=((HoldType)&&(HoldLen))?15:20;
if (ModP) Keep=20;
if ((PlayerCount<2)&&(StaticGarbHeight)) Keep=50;
IgnoreAfterHold = false;
}
else if (BotType==3) {
SearchDepth=12; Keep=30;
if (ModP==2&&0) {
SearchDepth=12; Keep=50;
}
IgnoreAfterHold = false;
}
else if (BotType==4) {
SearchDepth=12; Keep=30;
if (ModP==2) {
SearchDepth=12; Keep=50;
}
IgnoreAfterHold = false;
}
else if (BotType==5) {
SearchDepth=10; Keep=200;
IgnoreAfterHold = false;
}
else if (BotType==6) {
SearchDepth=7; Keep=20;
if (ModP==2) {
SearchDepth=12; Keep=20;
}
IgnoreAfterHold = false;
}
else if (BotType==7) {
SearchDepth=12; Keep=50;
IgnoreAfterHold = false;
}
else if (BotType==8) {
SearchDepth=3; Keep=10;
IgnoreAfterHold = false;
}
else if (BotType==9) {
SearchDepth=1; Keep=1;
if ((!HoldLen)||(!HoldType)) {
SearchDepth=2; Keep=4;
}
BotType = 6;
}
if ((Mod2==2)&&(SearchDepth>2)) {
Keep=max(Keep,min(200,SearchDepth*Keep)); SearchDepth=2;
}
if ((Mod2==2)&&(SearchDepth>3)) {
SearchDepth=2; Keep=max(Keep,100);
}
int Height=0, Bub=0, BubH=0, HoleHeight=0;
bool bb = ((BotType==6)||(BotType==7));
for (int i=LX; i; --i) {
int ls=0, lu=0;
for (int j=1; j<=LY; ++j) {
if (CheckGrid(i,j)) Height=max(Height,i);
bool dn = CheckGrid(i-1,j);
if ((!CheckGrid(i+1,j))||(i==LX)) lu=j;
if ((!CheckGrid(i,j))&&
((CheckGrid(i,j-1))||((dn)&&(bb)&&(j==2)))&&
((CheckGrid(i,j+1))||((dn)&&(bb)&&(j==LY-1)))&&
(CheckGrid(i+1,j))&&((CheckGrid(i-1,j))||((PlayerCount>1)&&(Height+10>SX)))) {
++Bub; BubH=max(BubH,i);
}
else if ((!CheckGrid(i,j))&&(CheckGrid(i,j+1))&&(ls>=lu)) {
++Bub; BubH=max(BubH,i);
}
if (CheckGrid(i,j)) ls=j;
if ((!CheckGrid(i,j))&&(CheckGrid(i+1,j))) HoleHeight=max(i,HoleHeight);
}
}
PreHeight = Height;
int TotHeight = Height+min((((BotType==1)||(BotType==3))&&(QPMode)&&((WindUpCD)||(TQPScore<=1300000LL)))?5:999,int(AttackIn.size()));
if ((TotHeight<=6)&&(Bub<2)&&((Combo<3)||(B2B>=3))) SpinMode=true;
//if ((!ModM)&&(Gen.Pool.size()<15)&&(PlayerCount>1)&&(TotHeight+10<SX)&&(Bub<2)&&((!Combo)||(B2B>=5))) SpinMode=true;
if (TotHeight+(((PlayerCount<2)||(Gen.Pool.size()<18)||((B2B>=10)&&(TQPScore<2000000LL)))?5:10)>SX) SpinMode=false;
if ((Height<=SX-5)&&(CurZone)) SpinMode=true;
if ((BotType==6)||(BotType==7)) {
if (Mod2==2) {
if (TotHeight+9>SX) SpinMode=false;
}
int mn=LX+1, p=0;
for (int i=1; i<=LY; ++i) {
if ((i>=2)&&(i<=LY-1)) continue;
int cur = 0;
for (int j=LX; j; --j) {
if (CheckGrid(j,i)) {
cur=j; break;
}
}
if (cur<mn) {
mn=cur; p=i;
}
}
for (int i=1; i<=LY; ++i) {
if ((i==1)||(i==LY)) continue;
int cur = 0;
for (int j=LX; j; --j) {
if (CheckGrid(j,i)) {
cur=j; break;
}
}
if (cur<mn) {
mn=cur; p=i;
}
}
if ((((p!=1)&&(p!=LY)))||(BubH>mn)) BotType=2;
else if (!SpinMode) BotType=2;
else {
int d=(p==1)?1:-1, acc=0;
for (int i=mn+1; i<=LX; ++i) {
int j=p, cnt=0;
for (int jj=1; jj<LY; ++jj) {
j += d;
if (CheckGrid(i,j)) {
if (jj>1) break;
}
else ++cnt;
}
if (cnt>=LY-1) break;
if (cnt) acc+=cnt;
else if ((acc)&&(acc<3)) {
if ((mn)||(PlayerCount>1)) BotType=2;
BotType=2; break;
}
else acc=0;
}
}
}
while (Hold.size()>HoldLen) Hold.pop_back();
FillNext(SearchDepth+HoldLen+1);
if (!CheckActive()) return false;
Current = new Status(LX, LY);
Current->Cur=Cur; Current->Hold=Hold; Current->Next=Next;
Current->LineAfterPC = LineAfterPC;
Current->LastClearType = LastClearType;
Current->Combo = Combo;
Current->Clutch = CurClutch;
/*if ((GetT)&&(SpinMode)) {
bool f = (Current->Cur.GetName()=="T");
for (Piece &o : Current->Hold) f|=(o.GetName()=="T");
for (int i=0; i<SearchDepth-1; ++i) {
if (f) break;
if (Current->Next[i].GetName()=="T") f=true;
}
if (!f) Current->Next[max(0,SearchDepth-1)]=P_T;
}*/
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) Current->B[i][j]=((B[i][j])&&(!C[i][j]));
}
CurLayer = {Current};
Map = new AccessMap(LX,LY);
Tmp = new AccessMap(LX,LY);
FinalInst = (Instruction){-1,0,0,0,false};
FinalStepInst = (Instruction){-1,0,0,0,false};
return true;
}
bool SearchLayer(int i) {
vector<pair<Status*,ll> > NextLayer;
vector<llu> NextHash;
int LayerKeep = Keep;
//if ((BotType==1)&&(i>1)) Keep=10;
bool Final=(i+1==SearchDepth); ll FinalEval=-4000000000000000000LL;
for (Status *Sta : CurLayer) {
vector<pair<int,Piece> > PieceOpt = {make_pair(0,Sta->Cur)};
vector<llu> PieceHash = {Sta->Cur.GetHash()};
int Holds = 0;
if (HoldType==1) Holds=min(HoldLen,HoldRem);
if (HoldType==2) Holds=HoldLen;
int hp = (BotType==5)?3:1;
if ((i>=hp)&&(IgnoreAfterHold)) Holds=0;
int id = 0;
int StaHeight = 0;
for (int ii=1; ii<=LX; ++ii) {
for (int jj=1; jj<=LY; ++jj) {
if (Sta->B[ii][jj]) StaHeight=max(StaHeight,ii);
}
}
for (int j=0; j<int(HoldLen-Sta->Hold.size()); ++j) {
if (++id>Holds) break;
llu hsh=Sta->Next[j].GetHash(); bool f=true;
for (llu k : PieceHash) {
if (hsh==k) {
f=false; break;
}
}
if (f) {
PieceOpt.push_back(make_pair(id,Sta->Next[j])); PieceHash.push_back(hsh);
}
}
for (Piece &p : Sta->Hold) {
if (++id>Holds) break;
llu hsh=p.GetHash(); bool f=true;
for (llu k : PieceHash) {
if (hsh==k) {
f=false; break;
}
}
if (f) {
PieceOpt.push_back(make_pair(id,p)); PieceHash.push_back(hsh);
}
}
for (pair<int,Piece> &o : PieceOpt) {
vector<Piece> NewNext=Sta->Next, NewHold=Sta->Hold; Piece NewCur=Sta->Cur;
for (int j=0; j<o.first; ++j) {
if (NewHold.size()==HoldLen) {
Piece tmp = NewHold[0];
for (int i=0; i+1<HoldLen; ++i) NewHold[i]=NewHold[i+1];
NewHold[HoldLen-1] = NewCur;
NewCur = tmp;
}
else {
NewHold.push_back(NewCur);
NewCur = NewNext[0];
for (int k=0; k+1<NewNext.size(); ++k) NewNext[k]=NewNext[k+1];
NewNext.pop_back();
}
}
NewCur=NewNext[0]; for (int j=0; j+1<NewNext.size(); ++j) NewNext[j]=NewNext[j+1];
NewNext.pop_back();
GetAccessMap(Map, Sta, o.second);
Piece p = o.second;
vector<pair<PosTuple,bool> > Locations = GetLocations(Map, Tmp, p, StaHeight, ((i)||(o.first))?0:BeginInc,
(IsSpinBonus(p.GetName()))||(((BotType==1)||(BotType==3))&&(SpinRule==SR_Default)), Sta->Clutch);
if (Locations.empty()) break;
for (pair<PosTuple,bool> pr : Locations) {
PosTuple oo = pr.first;
Status *NewSta = nullptr;
if (Recycle.empty()) NewSta=new Status(*Sta);
else {
NewSta=Recycle.back(); Recycle.pop_back();
*NewSta = *Sta;
}
int PLX = p.GetLX();
int Unmoveable = 0;
for (int ii=0; ii<PLX; ++ii) {
for (int jj=0; jj<PLX; ++jj) {
if (!p.GetGrid(ii,jj,oo.d)) continue;
int x=oo.x+ii, y=oo.y+jj;
if (NewSta->CheckGrid(x+1,y)) Unmoveable|=1;
if (NewSta->CheckGrid(x-1,y)) Unmoveable|=2;
if (NewSta->CheckGrid(x,y+1)) Unmoveable|=4;
if (NewSta->CheckGrid(x,y-1)) Unmoveable|=8;
}
}
if (!i) NewSta->Inst=(Instruction){o.first,oo.d,oo.x,oo.y,((pr.second)||(Unmoveable==15))};
for (int ii=0; ii<PLX; ++ii) {
for (int jj=0; jj<PLX; ++jj) {
if (p.GetGrid(ii,jj,oo.d)) NewSta->B[oo.x+ii][oo.y+jj]=true;
}
}
NewSta->Next=NewNext; NewSta->Hold=NewHold; NewSta->Cur=NewCur;
int pp=-1; ll TmpEval=Eval(NewSta,p,oo,Unmoveable==15,oo.d,oo.x,oo.y,pr.second);
ll hsh = NewSta->GetHash((HoldType)?HoldLen:0);
ll NewEval = TmpEval+NewSta->AccEval;
if (Final) {
if (NewEval>FinalEval) {
FinalEval=NewEval; FinalStepInst=NewSta->Inst;
}
Recycle.push_back(NewSta); continue;
}
int sc=0, sp=-1;
for (int i=0; i<NextHash.size(); ++i) {
if (hsh==NextHash[i]) pp=i;
/*if (NextLayer[i].first->Inst==NewSta->Inst) {
++sc;
if (sp<0) sp=i;
else if (NextLayer[sp].second>NextLayer[i].second) sp=i;
}*/
}
if (pp>=0) {
if (NewEval>NextLayer[pp].second) {
NextLayer[pp].second = NewEval;
Recycle.push_back(NextLayer[pp].first);
NextLayer[pp].first = NewSta;
}
else Recycle.push_back(NewSta);
}
/*else if ((sp>=0)&&(SameInstLim>0)&&(sc>=SameInstLim)) {
if (NewEval>NextLayer[sp].second) {
Recycle.push_back(NextLayer[sp].first);
NextLayer[sp].first=NewSta; NextLayer[sp].second=NewEval;
NextHash[sp] = hsh;
}
else Recycle.push_back(NewSta);
}*/
else {
if (NextLayer.size()<LayerKeep) {
NextLayer.push_back(make_pair(NewSta, NewEval));
NextHash.push_back(hsh);
}
else {
int p = 0;
for (int i=1; i<NextLayer.size(); ++i) {
if (NextLayer[i].second<NextLayer[p].second) p=i;
}
if (NewEval>NextLayer[p].second) {
Recycle.push_back(NextLayer[p].first);
NextLayer[p].first=NewSta; NextLayer[p].second=NewEval;
NextHash[p] = hsh;
}
else Recycle.push_back(NewSta);
}
}
}
}
if (i) Recycle.push_back(Sta);
}
CurLayer.clear();
if (Final) {
if (FinalStepInst.ord>=0) FinalInst=FinalStepInst;
return true;
}
bool AllSame = false;
if (NextLayer.size()) {
int pos = 0;
for (int i=1; i<NextLayer.size(); ++i) {
if (NextLayer[i].second>NextLayer[pos].second) pos=i;
}
FinalInst = NextLayer[pos].first->Inst;
AllSame = true;
for (pair<Status*,ll> o : NextLayer) {
if (o.first->Inst!=FinalInst) {
AllSame=false; break;
}
}
}
for (pair<Status*,ll> o : NextLayer) CurLayer.push_back(o.first);
NextLayer.clear();
if (AllSame) return true;
return false;
}
vector<Action> SearchEnd() {
for (Status *p : CurLayer) delete p;
CurLayer.clear();
Piece p=P_Empty; int k=FinalInst.ord;
if (k<0) {
delete Map; delete Tmp;
delete Current; return {A_HardDrop};
}
if (!k) p=Cur;
else if (k<=HoldLen-Hold.size()) p=Next[k-1];
else p=Hold[k-HoldLen+Hold.size()-1];
GetAccessMap(Map, Current, p);
pair<int,int> Place=SpawnPlace(p), Anch[4];
Piece NewP = p;
for (int i=0; i<4; ++i) {
NewP.SetDir(i); Anch[i]=NewP.GetAnchor();
}
int d=DefaultDir, x=Place.first+Anch[d].first, y=Place.second+Anch[d].second;
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
TmpKick[i][j] = GetKickTable(i,j,p.GetRealName(),RotateSystem);
for (pair<int,int> &o : TmpKick[i][j]) {
swap(o.first, o.second);
o.first += Anch[j].first-Anch[i].first;
o.second += Anch[j].second-Anch[i].second;
}
}
}
for (int d=0; d<4; ++d) {
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) Tmp->B[d][i][j]=Map->B[d][i][j];
}
}
int od=FinalInst.d, ox=FinalInst.x+Anch[od].first, oy=FinalInst.y+Anch[od].second;
Tg=NewP; TgD=FinalInst.d; TgX+=FinalInst.x; TgY=FinalInst.y;
vector<Action> SearchRes = FinalSearch(Map,Tmp,d,x+((k)?0:BeginInc),y,od,ox,oy,FinalInst.sp,IsHalfSame(p.GetRealName()),((CurClutch)||(PreInc)||(HoldPosInc+BeginInc)));
vector<Action> res(k, A_Hold);
if (SearchRes.empty()) res.push_back(A_HardDrop);
else {
for (Action o : SearchRes) res.push_back(o);
}
delete Map; delete Tmp;
delete Current;
if (BoardID) {
for (Status *o : Recycle) delete o;
Recycle.clear();
}
return res;
}
int SearchStep = -1;
vector<Action> SearchNext(bool ByStep=false) {
TgD = -1;
if ((ByStep)||(SearchStep!=-1)) {
if (SearchStep==-1) {
if (SearchBegin()) SearchStep=0;
}
else if (SearchStep==-2) {
SearchStep=-1; return SearchEnd();
}
else {
bool f = SearchLayer(SearchStep);
if ((++SearchStep>=SearchDepth)||(f)) SearchStep=-2;
}
return vector<Action>();
}
if (!SearchBegin()) return vector<Action>();
for (int i=0; i<SearchDepth; ++i) {
if (SearchLayer(i)) break;
}
SearchStep = -1;
return SearchEnd();
}
int B2BColor(int x) {
if (B2BRule==BR_Techmino) {
if (B2B<50) return 0x888888;
if (B2B<=800) return 0xFF6666;
return 0x9999FF;
}
if (x<1) return (B2BRule==BR_Chain)?0xAA0000:0x888888;
if (x<4) return 0xFFE211;
if ((B2BRule!=BR_Surge)&&(B2BRule!=BR_QP)) return 0xFFE211;
vector<pair<int,int> > lst={{4,0x00FFCC},{13,0xFFFF00},{31,0xFF0000},{45,0xDF3782},{70,0xAF2FFF},{90,0x0080FF},
{130,0x66CCFF},{150,0x99FFFF},{220,0xE5E59C}};
int rr = -1;
for (int i=1; i<lst.size(); ++i) {
if ((lst[i-1].first<=x)&&(x<=lst[i].first)) rr=Mix(lst[i].second,lst[i-1].second,double(x-lst[i-1].first)/double(lst[i].first-lst[i-1].first));
}
if ((rr<0)&&(x<=lst[0].first)) rr=lst[0].second;
else if (rr<0) rr=lst.back().second;
if (Mod8==2) rr=Mix(0xFFFFFF,0xFFFFFF^rr,0.4);
return rr;
}
int GetHeight() {
for (int i=LX; i; --i) {
for (int j=1; j<=LY; ++j) {
if (CheckGrid(i,j)) return i;
}
}
return 0;
}
int GetPaintColor() {
if (PaintType==1) return P_Z.GetColor();
if (PaintType==2) return P_L.GetColor();
if (PaintType==3) return P_O.GetColor();
if (PaintType==4) return P_S.GetColor();
if (PaintType==5) return P_I.GetColor();
if (PaintType==6) return P_J.GetColor();
if (PaintType==7) return P_T.GetColor();
if (PaintType==8) return Garb;
return 0x39C5BB;
}
int ModPos = 0;
void PrintQPMod(int val, int clr, string s, string ss) {
if (!val) return;
double x=double(++ModPos)*1.5, y=LY+5;
if (val==1) Poly(x,y,0.6,4,clr,acos(-1.0)*0.25);
else {
Poly(x, y, 1, 4, 0xFF6666, 0);
Poly(x, y, 1, 4, 0xFF6666, acos(-1.0)*0.25);
}
double dd = (val==1)?1.0:1.5;
PrintStrM((val==1)?s:ss, x-0.25*dd, y-0.2*dd, 0.8*dd, (val==1)?Mix(0x000000,clr,0.5):0xFFFFFF, 0.2);
}
int GetLevelColor(int x) {
return LevelColor[max(0,min(int(LevelColor.size())-1,x))];
}
void PaintZenith() {
double len = min(8,LY)*1.5;
int MaxLevel = int(QPLevelScore.size());
int CurLevel = max(1,min(MaxLevel,Level));
int pp = 0;
int SurgeCount = 0;
if (B2B>4) {
if (B2BRule==BR_Surge) SurgeCount=B2B-1;
if (B2BRule==BR_QP) SurgeCount=B2B-4;
}
int OriSurgeCount = SurgeCount;
SurgeCount = max(0,SurgeCount-int(AttackIn.size()));
ll SurgeScore = DQPScore+ll(SurgeCount)*250LL*ll(QPRank+1);
if (SurgeCount<1) SurgeScore=-1LL;
int BegLevel = max(9,CurLevel);
for (int i=0; i<QPLevelScore.size(); ++i) {
if (SurgeScore>QPLevelScore[i]*1000LL) BegLevel=max(BegLevel,i+1);
}
int SurgeRank = QPRank;
if (OriSurgeCount>0) {
ll _Exp = QPExp;
if (SurgeCount) _Exp+=500+10000*min(SurgeCount,10000);
if (SurgeCount<OriSurgeCount) _Exp+=500+10000*(((Mod5==2)||(Mod9==2)||(ModD==2))?0:OriSurgeCount-SurgeCount);
_Exp = max(_Exp,0LL);
for (;;) {
ll req = max(40000LL,40000LL*(SurgeRank+1));
if ((SurgeRank>100)||(_Exp<req)) break;
SurgeRank+=_Exp/req; _Exp-=req;
}
}
for (int i=14; i>=0; --i) {
int d=BegLevel-i; if (d<1) continue;
ll Lower=QPLevelScore[d-1]*1000LL, Upper=(d==MaxLevel)?max(Lower+1000LL,DQPScore):QPLevelScore[d]*1000LL;
if (d>Level) {
PrintStrL("Stage "+IToS(d), i*2, LY+6, 0.7, 0x888888);
Rect(i*2+1, LY+6, 0.3, len, 0x444444);
}
else {
PrintStrL("Stage "+IToS(d), i*2, LY+6, 0.7, 0xCCCCCC);
Rect(i*2+1, LY+6, 0.3, len, 0x888888);
ll t=Time; if (QPSegTime.size()>d-1) t=QPSegTime[d-1];
PrintStrR(IToS(t/1000LL/60LL)+":"+IToS(t/1000LL%60LL/10LL)+IToS(t/1000LL%60LL%10LL)+"."+IToS(t%1000LL/100LL)+" ", i*2, LY+6+len, 0.7, (d==CurLevel)?0xFDD000:0xDDDDDD);
for (int j=pp; j<QPSeg.size(); ++j) {
pair<int,pair<ll,ll> > o = QPSeg[j];
ll l=max(Lower,o.second.first), r=min(min(Upper,DQPScore),o.second.second);
if (o.second.second<=Upper) pp=j+1;
if (l>Upper) break;
if (l>=r) continue;
Rect(i*2+1, LY+6+len*double(l-Lower)/double(Upper-Lower), 0.3, len*double(r-l)/double(Upper-Lower), Mix(0x000000,abs(o.first),0.3));
if (o.first<0)
Rect(i*2+1+0.15, LY+6+len*double(l-Lower)/double(Upper-Lower), 0.15, len*double(r-l)/double(Upper-Lower), abs(o.first));
}
}
if ((SurgeScore>=Lower)&&(SurgeScore<=Upper)) {
Rect(i*2+1-0.1,LY+6+len*double(SurgeScore-Lower)/double(Upper-Lower)-0.05,0.1,0.1,GetLevelColor(SurgeRank));
Rect(i*2+1,LY+6+len*double(SurgeScore-Lower)/double(Upper-Lower)-0.05,0.3,0.1,0xDDDDDD);
}
if ((DQPScore>=Lower)&&(DQPScore<=Upper))
Rect(i*2+1-0.1,LY+6+len*double(DQPScore-Lower)/double(Upper-Lower)-0.05,0.4,0.1,0xFDD000);
}
}
void Paint() {
if (K<0.001) return;
bool Simple = ((Bot)&&(K*double(GetSize())<8.0));
if ((QPMode)&&(!Simple)) PaintZenith();
if (!Simple) {
Rect(2, 0, SX-2, LY, ((QPBlighted)||(CurZone))?Mix(0xFFE211,GridColor,0.3):GridColor);
Rect(0, 0, 2, LY, ((QPBlighted)||(CurZone))?Mix(0xFFE211,OverGridColor,0.3):OverGridColor);
for (int i=0; i<SX; ++i) {
for (int j=0; j<LY; ++j) {
int clr = BoardColor;
if (SX-i<=RoundHeight) clr=RoundColor;
if ((VanishHeight)&&(SX-i>=VanishHeight)) clr=VanishColor;
Square(i+0.025, j+0.025, 0.95, clr);
}
}
}
else Rect(0,0,SX,LY,BoardColor);
int FallDist = LX;
for (int j=1; j<=LY; ++j) {
int pre = 0;
for (int i=1; i<=LX; ++i) {
if (C[i][j]) FallDist=min(FallDist,i-pre-1);
else if (B[i][j]) pre=i;
}
}
bool Inactive=false, CDown=CheckDown();
double FallRate=0.0, LockRate=0.0, ClearRate=0.0;
if (CDown) {
if ((DropDelay)&&(SmoothLevel>=1)) FallRate=max(0.0,min(1.0,double(FallTime)/double(DropDelay)));
else FallRate=0.0;
}
else {
if (LockDelay>0) LockRate=max(0.0,min(1.0,double(FallTime)/double(LockDelay)));
else if (!LockDelay) LockRate=0.0;
}
if ((InactiveTime>0)&&(InactiveTot>0)) {
Inactive = true;
ClearRate = 1.0-max(0.0,min(1.0,double(InactiveTime)/double(InactiveTot)));
}
double grat = max(0.0,min(1.0,double(PushCD)/double(max(1,GarbagePush))));
if (!SmoothLevel) grat=0.0;
if ((ShadowType==2)&&(!Simple)) {
for (int j=1; j<=LY; ++j) {
bool f = false;
for (int i=1; i<=LX; ++i) {
if (C[i][j]) f=true;
}
if (!f) continue;
for (int i=1; i<=SX; ++i)
Square(SX-i+grat+0.025,j-1+0.025,0.95,ShadowColor);
}
}
if ((UseTip)&&((TgD>=0)&&(TgD<4))) {
int PLX = Tg.GetLX();
for (int i=0; i<PLX; ++i) {
for (int j=0; j<PLX; ++j) {
int b = Tg.GetGrid(i,j,TgD);
if (!b) continue;
int x=i+TgX, y=j+TgY;
Square(SX-x+0.025, y-1+0.025, 0.95, Mix(abs(b),BackgroundColor,0.3));
}
}
}
if ((ShadowType==1)&&(!Simple)) {
for (int i=1; i<=SX; ++i) {
for (int j=1; j<=LY; ++j) {
if ((!CheckOut(i+FallDist,j))&&(C[i+FallDist][j])) Square(SX-i+grat+0.025,j-1+0.025,0.95,ShadowColor);
}
}
}
if (SelX) {
int clr = 0x39C5BB;
if (!CursorMode) clr=0x66CCFF;
Square(SX-SelX+0.025, SelY-1+0.025, 0.95, Mix(clr,BackgroundColor,0.3));
}
int RiseHeight=GetRiseHeight(), GarbID=-1;
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if ((B[i][j]<0)&&(!C[i][j])) {
++GarbID; break;
}
}
}
if ((NextLen)&&(!Simple)) PrintStrM("NEXT",0,LY+2.5,1,0xEEEEEE,0.12);
if ((SmoothLevel<=3)||(NextLen<2)||((Bot)&&(BotSpeed<100))) DNext=0;
for (int i=0; i<NextLen; ++i) {
Piece p = (Next.size()>i)?Next[i]:P_Empty;
if (i<5) PaintPiece(p,(double(i)+DNext)*3.5+1,LY+1,3);
else {
int d = i-5;
PaintPiece(p, 1.5+1.2*(d%15), LY+1.2*(d/15)+5, 1, p.GetColor(), S_Simple);
}
}
if ((HoldType)&&(HoldLen)) {
if (!Simple) PrintStrM("HOLD",0,-2.5,1,((HoldRem)||(HoldType==2))?0xEEEEEE:0x888888, 0.12);
for (int i=0; i<HoldLen; ++i) {
int clr = -1;
if ((HoldType==1)&&(i+HoldLen-Hold.size()>=HoldRem)) clr=0x888888;
PaintPiece((Hold.size()>i)?Hold[i]:P_Empty, i*3.5+1, -4, 3, clr);
}
}
int ZoneID = 0;
for (int i=1; i<=LX; ++i) {
bool gb = false;
for (int j=1; j<=LY; ++j) {
int clr = abs(B[i][j]);
if (B[i][j]<0) gb=true;
if (!clr) continue;
if (C[i][j]) continue;
clr = Mix(0x000000,clr,0.1);
clr = Mix(0xFFFFFF,clr,0.3*max(0.0,min(1.0,double((Age[i][j]<0)?500:Age[i][j])/500.0)));
if (Mod7) {
double vrat = Age[i][j]/500.0;
if (Mod7==1) {
int d = int(Time%5000LL);
if (d<=500) vrat=max(vrat,double(500-d)/500.0);
}
if (B[i][j]<0) {
if (Mod7==1) vrat=1.0;
else vrat=max(vrat,double(3-GarbID)/3.0);
}
if ((B[i][j]>=GarbQuest)&&(B[i][j]<=GarbQuest+20)) vrat=1.0;
if (Bot) vrat=max(vrat,0.2);
if (vrat<0.001) continue;
clr = Mix(clr,BackgroundColor,vrat);
}
double di = 0.0;
if (Inactive) {
if (Age[i][j]<0) di+=Age[i][j]*ClearRate;
else if (FallDest[i]) di-=(i-FallDest[i])*ClearRate;
else {
double rat = max(0.0,min(1.0,ClearRate*LY-j+1));
if (rat>0.999) continue;
rat = 1.0-(1.0-rat)*(1.0-rat);
clr = Mix(0xFFFFFF,clr,0.3);
clr = Mix(BoardColor,clr,rat);
}
}
PaintGrid(i+di-((i<=RiseHeight)?0.0:grat), j, abs(clr), (B[i][j]<0)?S_Garbage:S_Default,
0, 0, 0,
U[i+1][j]==U[i][j], U[i-1][j]==U[i][j], U[i][j-1]==U[i][j], U[i][j+1]==U[i][j]);
if ((B[i][j]>=GarbQuest)&&(B[i][j]<=GarbQuest+20)) {
PrintStrM(IToS(B[i][j]-GarbQuest), SX-i+0.3, j-0.7, 0.7, 0xCC99FF);
}
if ((j==1)&&(B[i][j]==GarbZone)) ++ZoneID;
}
if (gb) --GarbID;
}
if (ZoneID) {
PrintStrM(IToS(ZoneID)+" Lines", SX-(ZoneID*0.5+0.5)+0.3-0.5, (LY*0.5+0.5)-0.7, 1, 0xFFFFFF);
PrintStrM(IToS(ZoneAttack+GetZoneBonus(ZoneID))+" Attack", SX-(ZoneID*0.5+0.5)+0.3+0.5, (LY*0.5+0.5)-0.7, 1, 0xFFFFFF);
}
double Cx=PosX+0.5*Cur.GetLX()-FallRate+PDx-grat, Cy=PosY+0.5*Cur.GetLX()+PDy;
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
int clr = abs(B[i][j]);
if (!clr) continue;
if (!C[i][j]) continue;
clr = Mix(0x000000,clr,0.1*LockRate);
PaintGrid(i-FallRate+PDx-grat, j+PDy, abs(clr), S_Active, PDth, Cx, Cy,
C[i+1][j], C[i-1][j], C[i][j-1], C[i][j+1]);
}
}
pair<int,int> NextPos = SpawnPlace(Next[0]);
int PLX = Next[0].GetLX();
double hrat = 1.0-max(0.0,min(1.0,(SX-GetHeight()-2)*0.15));
if (!Simple) {
for (int i=0; i<PLX; ++i) {
for (int j=0; j<PLX; ++j) {
if (!Next[0].GetGrid(i,j)) continue;
int x=i+NextPos.first, y=j+NextPos.second;
PrintStrM("*", SX-x+0.2, y-1+0.3, 1, Mix(0xFF0000,0xCCCCCC,hrat*0.3+0.7), 0.2*hrat);
}
}
}
for (int i=0; i<min(GarbagePreview,int(AttackIn.size())); ++i) {
for (int j=1; j<=LY; ++j) {
if (AttackIn[i].B[j]) PaintGrid(-i-0.5,j,Mix(abs(AttackIn[i].B[j]),BackgroundColor,max(0.2,0.8-0.1*i)),S_Garbage);
}
}
for (int i=1; i<=min(100,max(SX,int(AttackIn.size()))); ++i) {
int clr=0x333333; double w=0.15;
if ((GarbageGap>=0)&&(i<=GarbageGap)) clr=0x888888;
if (AttackIn.size()>=i) {
int del = AttackIn[i-1].Delay;
clr = Mix(0xFFE211,0xFF6666,max(0.0,min(1.0,double(del)*0.001)));
if (!AttackIn[i-1].Delay) clr=0xEE0000;
if (AttackIn[i-1].Delay<0) clr=0xDF3782;
if (AttackIn[i-1].Delay>GarbageDelay-GarbagePass) clr=Mix(0xFFFFFF,clr,0.3);
if ((GarbageGap>=0)&&(i>GarbageGap)) clr=Mix(0x000000,clr,0.3);
w = 0.2;
}
else if (Simple) continue;
Rect(SX-i+0.1, -0.2-0.5*w, 0.8, w, clr);
}
if ((AttackIn.size())&&(!Simple)) PrintStrR('-'+IToS(AttackIn.size()),SX,-0.5,0.8,0xFF6666,0.15);
double rat = 1.0;
if (!CDown) rat=1.0-LockRate;
if ((!Simple)&&(QPMode)) {
int sz = LevelColor.size();
int CurClr = LevelColor[max(0,min(sz-1,QPRank))];
int NextClr = LevelColor[max(0,min(sz-1,QPRank+1))];
if (NextClr==CurClr) CurClr=Mix(0x000000,CurClr,0.1);
double rat = max(0.0,min(1.0,double(QPExp)/double(QPExpReq())));
Rect(SX+0.5, 0, 0.25, LY, CurClr);
Rect(SX+0.5, LY*(1.0-rat)*0.5, 0.25, LY*rat, NextClr);
rat = max(0.0,min(1.0,double(QPExpDecCD)*0.0002));
Rect(SX+0.7, LY*(1.0-rat)*0.5, 0.05, LY*rat, 0xDDDDDD);
}
if (Simple) ;
else if (Bot) {
Rect(SX, 0, 0.5, LY, 0xCCCCCC);
if ((!HideStat)||(SelX)) {
PrintStrL(IToS(BotSpeed), SX+0.7, 0, 0.7, 0xDDDDDD);
PrintStrR(GetBotName(ActType), SX+0.7, LY-0.5, 0.7, 0xDDDDDD);
}
else PrintStrM("Autoplay Demonstration",SX+0.7,LY*0.5,0.6,0x66CCFF);
if (Menu=="home") PrintStrM("Click to Manually Control",SX+1.5,LY*0.5,0.5,0xBBBBBB);
}
else {
if (Inactive) rat=1.0;
Rect(SX, 0, 0.25, LY, 0xBBBBBB);
Rect(SX, 0, 0.25, LY*rat, Mix(0x888888,0xFFE211,(Inactive)?0.5:0));
PrintStrL((LockDelay<0)?"":IToS(((CDown)||(Inactive))?LockDelay:max(0,LockDelay-FallTime)), SX+0.7, 0, 0.7, 0xFFE211);
PrintStrR((ResetRem==Max)?"":IToS(ResetRem), SX+0.7, LY, 0.7, 0x39C5BB);
if (CursorMode) {
if (UsePlace) PrintStrR("Edit Mode",SX+1.4,LY,0.5,0xAAAAAA);
}
else if ((UseClick)&&(!CursorMoveLock)) PrintStrR("Cursor Control",SX+1.4,LY,0.5,0xAAAAAA);
if (UseUndo) {
int v = max(0,int(History.size())-HistoryPos-1);
PrintStrR(Str(12)+IToS(v),SX+0.25,-0.8,0.7,(v)?0x9999FF:0x888888);
v = max(0,HistoryPos);
PrintStrL(IToS(v)+Str(13),SX+0.25,LY+0.5,0.7,(v)?0x9999FF:0x888888);
}
rat = 0.0;
if (ResetLim) rat=max(0.0,min(1.0,double(ResetRem)/double(ResetLim)));
if (Inactive) rat=(ResetLim)?1.0:0.0;
Rect(SX+0.25, 0, 0.25, LY, 0x888888);
Rect(SX+0.25, 0, 0.25, LY*rat, Mix(0x888888,0x39C5BB,(Inactive)?0.5:0));
if (Menu=="home") PrintStrM("Click to Autoplay",SX+1.5,LY*0.5,0.5,0xBBBBBB);
}
if ((!Simple)&&(UseZone)) {
if (CurZone) PrintStrL("["+IToS(CurZone)+"] "+((ZoneRem>0)?IToS(ZoneRem):""),SX+1.5,0,0.7,0xFFE211);
else if ((!ZoneReq)||(ZoneProgress>=ZoneSeg*ZoneReq)) PrintStrL("["+IToS(ZoneSeg)+"] MAX",SX+1.5,0,0.7,0xFFA500);
else PrintStrL("["+IToS(ZoneProgress/ZoneReq)+"] +"+IToS(ZoneProgress%ZoneReq)+"/"+IToS(ZoneReq),SX+1.5,0,0.7,(ZoneProgress>=ZoneReq)?0xFFA500:0xAAAAAA);
}
if (Simple) ;
else if ((PlayerCount>2)&&(!QPMode)) {
PrintStrM(vector<string>({"None","All","Even","Elimination","Random",
"Payback","Badges","Attackers","Backfire"})[TargetType], SX+2, LY*0.5, 0.8, 0xCCCCCC);
}
else if ((UsePlace)&&(!Bot)&&(CursorMode)) {
PrintStrM("<"+vector<string>({"X","Z","L","O","S","I","J","T","G"})[PaintType]+">", SX+2, LY*0.5, 0.8, GetPaintColor());
}
if (Simple) ;
else if (Inactive) {
rat = max(0.0,min(1.0,double(InactiveTime)/double(max(1,InactiveTot))));
Rect(SX, LY*0.5*(1.0-rat)*double(Bot), 0.5, LY*rat, 0x888888);
//PrintStrL(IToS(InactiveTime), SX+1.4, 0, 0.7, 0x666666);
}
if (!Simple) {
ModPos = 0;
PrintQPMod(Mod2, 0xEE82EE, Str(22), "NH");
PrintQPMod(Mod3, 0xFFA500, Str(23), "MS");
PrintQPMod(Mod4, 0xFDD000, Str(24), "GV");
PrintQPMod(Mod5, 0xEE0000, Str(25), "VL");
PrintQPMod(Mod6, 0x66CCFF, Str(26), "DH");
PrintQPMod(Mod7, 0x9999FF, Str(27), "IN");
PrintQPMod(Mod8, 0x00FFCC, Str(28), "AS");
PrintQPMod(Mod9, 0xFFE211, Str(29), "EX");
PrintQPMod(ModS, 0x0080FF, Str(30), "SN");
PrintQPMod(ModP, 0xCCCCCC, "?", "PT");
PrintQPMod(ModM, 0xAAAAAA, "?", "MT");
}
if (AllClearAge>=5000) AllClearAge=5000;
else if (!Simple) {
double rat = 1.0-max(0.0,min(1.0,AllClearAge/5000.0));
PrintStrM("ALL", 0.5*SX-1, 0.5*LY-0.4, 2, 0xFFE211, 0.15*rat);
PrintStrM("CLEAR", 0.5*SX+1, 0.5*LY-0.4, 2, 0xFFE211, 0.15*rat);
}
if ((Mod8)&&(SpinText==LastClearType.first)&&(SpinText.size())) SpinAge=min(SpinAge,3000);
if (SpinAge>=5000) SpinAge=5000;
else if (!Simple) {
double rat = 1.0-max(0.0,min(1.0,SpinAge/5000.0));
double rr = 1.0-(1.0-rat)*(1.0-rat);
if (SpinGrade==3) PrintAction(SpinText+"-Spin", 4.5, -2, 0.8, Mix(SpinColor,BackgroundColor,rr), 0.15*rr, 1.5-0.5*rat*rat*rat*rat*rat);
else if (SpinGrade==2) PrintAction("Mini "+SpinText+"-Spin", 4.5, -2, 0.7, Mix(SpinColor,BackgroundColor,rr), 0.15*rr, 1.5-0.5*rat*rat*rat*rat*rat);
else if (SpinGrade==1) {
PrintAction("Mini", 4.3, -2, 0.55, Mix(SpinColor,BackgroundColor,rr), 0.15*rr, 1.5-0.5*rat*rat*rat*rat*rat);
PrintAction(SpinText+"-Spin", 4.7, -2, 0.55, Mix(SpinColor,BackgroundColor,rr), 0.15*rr, 1.5-0.5*rat*rat*rat*rat*rat);
}
else PrintAction(SpinText, 4.5, -2, 0.8, Mix(SpinColor,BackgroundColor,rr), 0.15*rr, 1.5-0.5*rat*rat*rat*rat*rat);
}
if ((Mod8)&&(LineClearText==LastClearType.second)) LineClearAge=min(LineClearAge,3000);
if (LineClearAge>=5000) LineClearAge=5000;
else if (!Simple) {
double rat = 1.0-max(0.0,min(1.0,LineClearAge/5000.0));
double rr = 1.0-(1.0-rat)*(1.0-rat);
string Text = (LineClearText>=0)?LineClearWord[min(LineClearText,int(LineClearWord.size()-1))]:"";
double dd = 6.0/min(6,max(1,int(Text.size())));
PrintAction(Text, 5.5, -2, 1.3, Mix(LineClearColor,BackgroundColor,rr), 0.15*rr, dd*(1.7-0.7*rat*rat*rat*rat*rat));
}
if (B2BAge>=5000) B2BAge=5000;
else if (!Simple) {
double rat = 1.0-max(0.0,min(1.0,B2BAge/5000.0));
double rr = 1.0-(1.0-rat)*(1.0-rat);
int clr = B2BColor(B2BText);
if (!((B2BBlinkRem/150)&1)) {
string str = "B2B *"+IToS(B2BText);
if (B2BRule==BR_Guildline) str="Back-to-Back";
if (B2BRule==BR_Techmino) str="B2B "+IToS(B2B/10)+"."+IToS(B2B%10)+"%";
PrintAction(str, 7, -2, 0.8, Mix(clr,BackgroundColor,rr), 0.15*rr, 1.5-0.5*rat*rat*rat*rat*rat);
}
}
if (ComboAge>=5000) ComboAge=5000;
else if (!Simple) {
double rat = 1.0-max(0.0,min(1.0,ComboAge/5000.0));
double rr = 1.0-(1.0-rat)*(1.0-rat);
int clr = (ComboText)?Mix(0xFFFFFF,0x39C5BB,(double(min(21,ComboText)-1)/20.0)):0x888888;
PrintAction(IToS(ComboText)+" Combo", 8, -2, 0.8, Mix(clr,BackgroundColor,rr), 0.15*rr, 1.5-0.5*rat*rat*rat*rat*rat);
}
double StatEnd = max(SX,((SX<4)?20:22));
if ((!HideStat)&&(!Simple)) {
if (QPMode) {
PrintStrR("Boost", StatEnd-12.8, -2, 0.7, 0xEEEEEE);
PrintStrR(IToS(QPRank), StatEnd-12, -2.1, 1, 0x99FFFF, 0.13);
if (PlayerCount>1) PrintStrR(IToS(KOCount)+" KO\'s", StatEnd-11, -2, 0.7, 0x99FFFF);
}
else if (PlayerCount>1) {
PrintStrR("Badge", StatEnd-12.8, -2, 0.7, 0xEEEEEE);
PrintStrR(IToS(Badge), StatEnd-12, -2.1, 1, 0x99FFFF, 0.13);
PrintStrR(IToS(KOCount)+" KO\'s", StatEnd-11, -2, 0.7, 0x99FFFF);
}
else if (UseLeveling()) {
PrintStrR("Level", StatEnd-11.8, -2, 0.7, 0xEEEEEE);
PrintStrR(IToS((Level<0)?max(LevBase,LevStart):Level), StatEnd-11, -2.1, 1, 0x99FFFF, 0.13);
}
ll t = abs(Time);
PrintStrR("Time", StatEnd-9.8, -2, 0.7, 0xEEEEEE);
int clr = 0x99FFFF;
if (Time<0LL) PrintStrR(Format("-%02d:%02d.",int(t/60000LL),int(t/1000LL%60LL)), StatEnd-9, -2.1, 1, 0x99FFFF, 0.13);
else {
if (TarTime) {
if (t<TarTime) {
clr=(TypeTime)?0xEE82EE:0xFDD000; t=TarTime-t;
}
else {
clr=(TypeTime)?0xFF6666:0x00FFCC; if (TypeTime) t=TarTime;
}
}
PrintStrR(Format("%02d:%02d.",int(t/60000LL),int(t/1000LL%60LL)), StatEnd-9, -2.1, 1, clr, 0.13);
}
PrintStrR(Format("%03lld",t%1000LL), StatEnd-8.8, -1, 0.65, clr, 0.14);
t = max(Time,1LL);
PrintStrR("Piece", StatEnd-7.8, -2, 0.7, 0xEEEEEE);
int val=TPiece; clr=0x99FFFF;
if (TarPiece) {
if (TPiece<TarPiece) {
clr=(TypePiece)?0xEE82EE:0xFDD000; val=TarPiece-TPiece;
}
else {
clr=(TypePiece)?0xFF6666:0x00FFCC; if (TypePiece) val=TarPiece;
}
}
PrintStrR(IToS(val), StatEnd-7, -2, 1, clr, 0.13);
PrintStrR(Format("%.2f /s",double(TPiece)/double(t)*1000.0), StatEnd-6, -2, 0.7, 0x99FFFF);
PrintStrR("Line", StatEnd-5.3, -2, 0.7, 0xEEEEEE);
val=TLine; clr=0x99FFFF;
if (TarLine) {
if (TLine<TarLine) {
clr=(TypeLine)?0xEE82EE:0xFDD000; val=TarLine-TLine;
}
else {
clr=(TypeLine)?0xFF6666:0x00FFCC; if (TypeLine) val=TarLine;
}
}
PrintStrR(IToS(val), StatEnd-4.5, -2, 1, clr, 0.13);
if ((TDig)||(TarDig)) {
int tmp = IToS(val).size();
val=TDig; clr=0x99FFFF;
if (TarDig) {
if (TDig<TarDig) {
clr=(TypeDig)?0xEE82EE:0xFDD000; val=TarDig-TDig;
}
else {
clr=(TypeDig)?0xFF6666:0x00FFCC; if (TypeDig) val=TarDig;
}
}
PrintStrR(IToS(val), StatEnd-4.3, -2-tmp*2.0/3.0, 0.7, clr, 0.13);
}
PrintStrR(Format("%.2f /m",double(TLine)/double(t)*60000.0), StatEnd-3.5, -2, 0.7, 0x99FFFF);
PrintStrR("Attack", StatEnd-2.8, -2, 0.7, 0xEEEEEE);
val=TAttack; clr=0x99FFFF;
if (TarAttack) {
if (TAttack<TarAttack) {
clr=(TypeAttack)?0xEE82EE:0xFDD000; val=TarAttack-TAttack;
}
else {
clr=(TypeAttack)?0xFF6666:0x00FFCC; if (TypeAttack) val=TarAttack;
}
}
PrintStrR(IToS(val), StatEnd-2, -2, 1, clr, 0.13);
if (IntRule==IR_Accumulate) {
int val = max(0,min(99,int(round(AttackAcc*100.0))));
PrintStrL(IToS(val/10)+IToS(val%10), StatEnd-1.7, -1.3, 0.7, 0x99FFFF, 0.13);
}
PrintStrR(Format("%.2f /m",double(TAttack)/double(t)*60000.0), StatEnd-1, -2, 0.7, 0x99FFFF);
if (Stock>0) {
PrintStrR("Stock", StatEnd-0.3, -2, 0.7, 0xEEEEEE);
PrintStrR(IToS((Over)?0:StockRem+1), StatEnd+0.5, -2, 1, clr, 0.13);