// -std=c++14 -lOpengl32

#pragma GCC optimize(3)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <random>
#include <algorithm>
#include <windows.h>
#include <conio.h>
#include <gl/gl.h>

using std::min; using std::max;
using std::swap; using std::reverse;
using std::sort; using std::stable_sort;
using std::pair; using std::make_pair;
using std::string; using std::vector;
using std::stack; using std::queue;
using std::deque; using std::set;
using std::mt19937; using std::shuffle;
using std::sprintf; using std::memset;
typedef long long ll;
typedef unsigned long long llu;
typedef __int128 lll;

WNDCLASS wc; HWND hWnd; HDC hDC; HGLRC hRC;
MSG msg; bool bQuit=false;
LRESULT CALLBACK WndProc(HWND _hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	switch (message) {
		case WM_CREATE:
			return 0;
		case WM_CLOSE:
			PostQuitMessage(0);
			return 0;
		case WM_DESTROY:
			return 0;
		case WM_KEYDOWN:
			/*switch (wParam) {
			case VK_ESCAPE:
				PostQuitMessage(0);
				return 0;
			}*/
			return 0;
		default:
			return DefWindowProc(_hWnd, message, wParam, lParam);
	}
}
void EnableOpenGL(HWND _hWnd, HDC *_hDC, HGLRC *_hRC) {
	PIXELFORMATDESCRIPTOR pfd; int iFormat;
	*_hDC = GetDC(_hWnd);
	ZeroMemory(&pfd, sizeof(pfd));
	pfd.nSize = sizeof(pfd);
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 24;
	pfd.cDepthBits = 16;
	pfd.iLayerType = PFD_MAIN_PLANE;
	iFormat = ChoosePixelFormat(*_hDC, &pfd);
	SetPixelFormat(*_hDC, iFormat, &pfd);
	*_hRC = wglCreateContext(*_hDC);
	wglMakeCurrent(*_hDC, *_hRC);
}
void DisableOpenGL(HWND _hWnd, HDC _hDC, HGLRC _hRC) {
	wglMakeCurrent(NULL, NULL);
	wglDeleteContext(_hRC);
	ReleaseDC(_hWnd, _hDC);
}

int Mix(int ca, int cb, double rt) {
	int Ar = (ca>>16);
	int Ag = ((ca>>8)&((1<<8)-1));
	int Ab = (ca&((1<<8)-1));
	int Br = (cb>>16);
	int Bg = ((cb>>8)&((1<<8)-1));
	int Bb = (cb&((1<<8)-1));
	int R = int(floor(rt*double(Ar)+(1.0-rt)*double(Br)));
	int G = int(floor(rt*double(Ag)+(1.0-rt)*double(Bg)));
	int B = int(floor(rt*double(Ab)+(1.0-rt)*double(Bb)));
	return (max(0,min(255,R))<<16)+(max(0,min(255,G))<<8)+max(0,min(255,B));
}
/*template<typename T>
T** NewGrid(int x, int y) {
	T** p = new T*[x];
	for (int i=0; i<x; ++i) p[i]=new int[y];
	return p;
}
template<typename T>
void DeleteGrid(T **p, int x, int y=0) {
	for (int i=0; i<x; ++i) delete[] p[i];
	delete[] p;
}*/
char PlaceholderString[10000];
#define Format(fmt,...) (sprintf(PlaceholderString,fmt,__VA_ARGS__),string(PlaceholderString))
vector<string> Char[256];
const int SToIErr = -998244353;
string IToS(ll x) {
	if (!x) return "0";
	string res=""; bool f=false;
	if (x<0LL) {
		x=-x; f=true;
	}
	while (x) {
		res=char(x%10LL+'0')+res; x/=10LL;
	}
	if (f) res='-'+res;
	return res;
}
string IToSH(ll x) {
	if (!x) return "000000";
	string res=""; bool f=false;
	if (x<0LL) {
		x=-x; f=true;
	}
	while (x) {
		int u = int(x%16LL);
		if (u<10) res=char(u+'0')+res;
		else res=char(u-10+'A')+res;
		x /= 16LL;
	}
	while (res.size()<6) res='0'+res;
	if (f) res='-'+res;
	return res;
}
string ToLower(string s) {
	for (char &ch : s) {
		if ((ch>='A')&&(ch<='Z')) ch+='a'-'A';
	}
	return s;
}
string Str(char ch) {
	return {ch};
}
int SToI(string s) {
	s = ToLower(s);
	if (s=="max") return 9999999;
	if (s=="true") return 1;
	if (s=="false") return 0;
	int res=0; bool f=false;
	for (int i=0; i<s.size(); ++i) {
		char ch = s[i];
		if (ch=='-') {
			if (!i) f=true;
			else return SToIErr;
		}
		else if ((ch>='0')&&(ch<='9')) res=min(9999999,res*10+ch-'0');
		else return SToIErr;
	}
	return (f)?-res:res;
}
const vector<string> KeyList = {"q","w","e","r","t","y","u","i","o","p",
"a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m",
"0","1","2","3","4","5","6","7","8","9",
"up","down","left","right","space","enter",
"ctrl","shift","tab","caps","none"};
char AskKey(string str) {
	if (str.empty()) return 0;
	if (str.size()==1) {
		char ch = str[0];
		if ((ch>='a')&&(ch<='z')) return ch+'A'-'a';
		if ((ch>='0')&&(ch<='9')) return ch;
		return 0;
	}
	if (str=="up") return VK_UP;
	if (str=="down") return VK_DOWN;
	if (str=="left") return VK_LEFT;
	if (str=="right") return VK_RIGHT;
	if (str=="shift") return VK_SHIFT;
	if (str=="space") return VK_SPACE;
	if (str=="tab") return VK_TAB;
	if (str=="enter") return VK_RETURN;
	if (str=="caps") return VK_CAPITAL;
	if (str=="ctrl") return VK_CONTROL;
	if (str=="none") return VK_F24;
	return 0;
}
string KeyChar(string str) {
	if (str.empty()) return 0;
	char ch = str[0];
	if (str=="up") return string("")+char(10);
	if (str=="down") return string("")+char(11);
	if (str=="left") return string("")+char(12);
	if (str=="right") return string("")+char(13);
	if (str=="space") return string("")+char(14);
	if (str=="shift") return string("")+char(15);
	if (str=="tab") return string("")+char(16);
	if (str=="enter") return string("")+char(17);
	if (str=="caps") return string("")+char(18);
	if (str=="ctrl") return string("")+char(19);
	if (str=="esc") return string("")+char(3);
	if (str=="none") return string("")+char(4);
	if ((ch>='a')&&(ch<='z')) return string("")+char(ch+'A'-'a');
	if ((ch>='A')&&(ch<='Z')) return string("")+char(ch);
	if ((ch>='0')&&(ch<='9')) return string("")+char(ch);
	return "";
}
string KeyChar(char ch) {
	if (ch==VK_UP) return string("")+char(10);
	if (ch==VK_DOWN) return string("")+char(11);
	if (ch==VK_LEFT) return string("")+char(12);
	if (ch==VK_RIGHT) return string("")+char(13);
	if (ch==VK_SPACE) return string("")+char(14);
	if (ch==VK_SHIFT) return string("")+char(15);
	if (ch==VK_TAB) return string("")+char(16);
	if (ch==VK_RETURN) return string("")+char(17);
	if (ch==VK_CAPITAL) return string("")+char(18);
	if (ch==VK_CONTROL) return string("")+char(19);
	if (ch==VK_ESCAPE) return string("")+char(3);
	if (ch==VK_F24) return string("")+char(4);
	if ((ch>='a')&&(ch<='z')) return string("")+char(ch+'A'-'a');
	if ((ch>='A')&&(ch<='Z')) return string("")+char(ch);
	if ((ch>='0')&&(ch<='9')) return string("")+char(ch);
	return "";
}
struct ConfigContent {
	string first, second;
	ConfigContent() {
		first=second="";
	}
	ConfigContent(string Name, string Val) {
		first=Name; second=Val;
	}
	ConfigContent(string Name, int Val) {
		first=Name; second=IToS(Val);
	}
	ConfigContent(pair<string,string> o) {
		first=o.first; second=o.second;
	}
	ConfigContent(pair<string,int> o) {
		first=o.first; second=IToS(o.second);
	}
};
int Scale = 500;
namespace PaintManager {
	const int PS = 20;
	void Plot(double x, double y, int clr) {
		int B=clr&255; clr>>=8;
		int G=clr&255; clr>>=8;
		int R = clr&255;
		double px = 1.0-x/double(PS);
		double py = y/double(PS);
		glColor3f(min(1.0,max(0.0,double(R)/255.0)), min(1.0,max(0.0,double(G)/255.0)), min(1.0,max(0.0,double(B)/255.0)));
		glVertex2f(py*2.0/3.0-1.0, px);
	}
	pair<double,double> RotatePos(double x, double y, double th, double rx, double ry) {
		if (fabs(th)<0.001) return make_pair(x,y);
		double d = sqrt((x-rx)*(x-rx)+(y-ry)*(y-ry));
		if (d<=0.001) return make_pair(x,y);
		th += atan2(y-ry,x-rx);
		return make_pair(rx+d*cos(th),ry+d*sin(th));
	}
	void Rect(double x, double y, double dx, double dy, int clr, double th=0.0, double rx=0.0, double ry=0.0) {
		glBegin(GL_POLYGON);
		pair<double,double> o = RotatePos(x,y,th,rx,ry);
		Plot(o.first, o.second, clr);
		o = RotatePos(x+dx,y,th,rx,ry);
		Plot(o.first, o.second, clr);
		o = RotatePos(x+dx,y+dy,th,rx,ry);
		Plot(o.first, o.second, clr);
		o = RotatePos(x,y+dy,th,rx,ry);
		Plot(o.first, o.second, clr);
		glEnd();
	}
	void Square(double x, double y, double d, int clr) {
		Rect(x, y, d, d, clr);
	}
	void Poly(double x, double y, double sz, int n, int clr, double th=0.0) {
		glBegin(GL_POLYGON);
		double dth = acos(-1.0)*2.0/double(n);
		th += 0.5*dth;
		for (int i=0; i<=n; ++i) {
			Plot(x+sz*cos(th), y+sz*sin(th), clr);
			th += dth;
		}
		glEnd();
	}
	void PrintChar(int ch, double x, double y, double sz, int clr, double bd=0.12, double th=0.0, double sc=0.0) {
		ch%=256; if (ch<0) ch+=256;
		bd*=sz; sz/=6.0;
		double mx=x+sz*3, my=y+sz*2.5;
		for (string str : Char[ch]) {
			if (str.size()==1) {
				int val = ((str[0]>='a')&&(str[0]<='z'))?str[0]-'a':26+str[0]-'0';
				double sx=x+sz*double(val/5), sy=y+sz*double(val%5);
				if ((th)||(sc)) {
					double dis = sqrt((sx-mx)*(sx-mx)+(sy-my)*(sy-my));
					dis = dis*(1.0+sc);
					if (dis>0.01) {
						double tt = atan2(sy-my,sx-mx);
						sx=mx+dis*cos(tt+th); sy=my+dis*sin(tt+th);
					}
				}
				double dx=bd*0.5, dy=bd*0.5;
				glBegin(GL_POLYGON);
				Plot(sx+dx, sy+dy, clr);
				Plot(sx+dx, sy-dy, clr);
				Plot(sx-dx, sy-dy, clr);
				Plot(sx-dx, sy+dy, clr);
				glEnd();
				continue;
			}
			for (int i=1; i<str.size(); ++i) {
				int val = ((str[i-1]>='a')&&(str[i-1]<='z'))?str[i-1]-'a':26+str[i-1]-'0';
				double sx=x+sz*double(val/5), sy=y+sz*double(val%5);
				val = ((str[i]>='a')&&(str[i]<='z'))?str[i]-'a':26+str[i]-'0';
				double ex=x+sz*double(val/5), ey=y+sz*double(val%5);
				if ((th)||(sc)) {
					double dis = sqrt((sx-mx)*(sx-mx)+(sy-my)*(sy-my));
					dis = dis*(1.0+sc);
					if (dis>0.01) {
						double tt = atan2(sy-my,sx-mx);
						sx=mx+dis*cos(tt+th); sy=my+dis*sin(tt+th);
					}
					swap(sx,ex); swap(sy,ey);
					dis = sqrt((sx-mx)*(sx-mx)+(sy-my)*(sy-my));
					dis = dis*(1.0+sc);
					if (dis>0.01) {
						double tt = atan2(sy-my,sx-mx);
						sx=mx+dis*cos(tt+th); sy=my+dis*sin(tt+th);
					}
					swap(sx,ex); swap(sy,ey);
				}
				double dx=ex-sx, dy=ey-sy, len=sqrt(dx*dx+dy*dy);
				double rat = bd/len*0.2;
				sx-=rat*dx; sy-=rat*dy;
				ex+=rat*dx; ey+=rat*dy;
				dx=sy-ey; dy=ex-sx;
				rat = 0.5*bd/sqrt((sx-ex)*(sx-ex)+(sy-ey)*(sy-ey));
				dx*=rat; dy*=rat;
				glBegin(GL_POLYGON);
				Plot(sx+dx, sy+dy, clr);
				Plot(ex+dx, ey+dy, clr);
				Plot(ex-dx, ey-dy, clr);
				Plot(sx-dx, sy-dy, clr);
				glEnd();
			}
		}
	}
	void PrintStrR(string str, double x, double y, double sz, int clr, double bd=0.12, double dis=1.0, string eff="", double th=0.0, double sc=0.0) {
		dis *= sz;
		reverse(str.begin(), str.end());
		for (char ch : str) {
			//if (sp) Rect(x+oo*sz*0.1-sz*0.2,y-sz*0.2,sz*1.5,sz,0xFF3333); 
			PrintChar(int(ch), x, y, sz, clr, bd, th, sc);
			y -= dis;
		}
	}
	void PrintStrL(string str, double x, double y, double sz, int clr, double bd=0.12, double dis=1.0, string eff="", double th=0.0, double sc=0.0) {
		PrintStrR(str, x, y+dis*sz*double(str.size()-1), sz, clr, bd, dis, eff, th, sc);
	}
	void PrintStrM(string str, double x, double y, double sz, int clr, double bd=0.12, double dis=1.0, string eff="", double th=0.0, double sc=0.0) {
		PrintStrR(str, x, y+dis*sz*double(str.size()-1)*0.5, sz, clr, bd, dis, eff, th, sc);
	}
}
class Piece {
	int **B[4], LX, Color, Dir;
	string Name;
	const Piece *From;
	public :
	Piece(int _LX=1, vector<vector<int> > _B=vector<vector<int> >(), int _Color=0xAAAAAA, string _Name="") {
		LX = max(1,min(100,_LX));
		Color = _Color;
		Name = _Name;
		Dir = 0;
		From = nullptr;
		for (int d=0; d<4; ++d) {
			B[d] = new int*[LX];
			for (int i=0; i<LX; ++i) B[d][i]=new int[LX];
		}
		for (int i=0; i<LX; ++i) {
			int pi = LX-i-1;
			for (int j=0; j<LX; ++j) {
				if ((_B.size()<=pi)||((_B[pi].size()<=j)||(!_B[pi][j]))) B[0][i][j]=0;
				else B[0][i][j]=_B[pi][j];
			}
		}
		for (int d=1; d<4; ++d) {
			for (int i=0; i<LX; ++i) {
				for (int j=0; j<LX; ++j) B[d][i][j]=B[d-1][j][LX-i-1];
			}
		}
	}
	Piece(const Piece &_From) {
		if (_From.From==nullptr) From=&_From;
		else From=_From.From;
		LX = From->LX;
		Color = From->Color;
		Dir = _From.Dir;
	}
	Piece operator=(const Piece &_From) {
		if (&_From==this) return *this;
		if ((From==nullptr)&&(_From.From==this)) {
			Color=_From.Color; Dir=_From.Dir; return *this;
		}
		if (From==nullptr) {
			for (int d=0; d<4; ++d) {
				for (int i=0; i<LX; ++i) delete[] B[d][i];
				delete[] B[d];
			}
		}
		if (_From.From==nullptr) From=&_From;
		else From=_From.From;
		LX = From->LX;
		Color = From->Color;
		Dir = _From.Dir;
		return *this;
	}
	~Piece() {
		if (From!=nullptr) return;
		for (int d=0; d<4; ++d) {
			for (int i=0; i<LX; ++i) delete[] B[d][i];
			delete[] B[d];
		}
	}
	inline int GetLX() const {
		return LX;
	}
	inline int GetRealGrid(int x, int y, int d=-1) const {
		if ((d<0)||(d>3)) d=Dir;
		if (((x<0)||(y<0))||((x>=LX)||(y>=LX))) return 0;
		int val = 0;
		if (From==nullptr) val=B[d][x][y];
		else val=From->B[d][x][y];
		return val;
	}
	inline int GetGrid(int x, int y, int d=-1) const {
		if ((d<0)||(d>3)) d=Dir;
		if (((x<0)||(y<0))||((x>=LX)||(y>=LX))) return 0;
		int val = 0;
		if (From==nullptr) val=B[d][x][y];
		else val=From->B[d][x][y];
		if (val==1) return Color;
		if (val==-1) return -Color;
		return val;
	}
	inline int GetShapeMid() const {
		int mn=LX-1, mx=0;
		for (int j=0; j<LX; ++j) {
			for (int i=0; i<LX; ++i) {
				if (GetGrid(i,j,Dir)) {
					mn=min(mn,j); mx=max(mx,j);
					break;
				}
			}
		}
		if ((mn<=(LX>>1))&&((LX>>1)<=mx)) return LX>>1;
		return (mx+mn)>>1;
	}
	inline int GetColor() const {
		if (From==nullptr) return Color;
		return From->Color;
	}
	string GetRealName() const {
		if (From==nullptr) return Name;
		return From->Name;
	}
	string GetName() const {
		if (From==nullptr) return Name;
		string tmp = From->Name;
		if ((tmp.size()<3)||(tmp[tmp.size()-2]!='@')) return tmp;
		return tmp.substr(0,tmp.size()-2);
	}
	int GetDir() const {
		return Dir;
	}
	void SetDir(int val) {
		Dir = val%4;
		if (Dir<0) Dir+=4;
	}
	pair<int,int> GetAnchor(int d=-1) {
		if ((d<0)||(d>3)) d=Dir;
		for (int i=0; i<LX; ++i) {
			for (int j=0; j<LX; ++j) {
				if (GetGrid(i,j,d)) return make_pair(i,j);
			}
		}
		return make_pair(0,0);
	}
	llu GetHash() const {
		if (From!=nullptr) return llu(From);
		return llu(this);
	}
};
bool Focus = false;
bool UniformKeySta[256];
void UpdateKeySta() {
	for (int i=0; i<256; ++i) {
		if (Focus) UniformKeySta[i]=bool(GetAsyncKeyState(i)&0x8000);
		else UniformKeySta[i]=false;
	}
}
bool CheckKey(int ch) {
	if ((ch<0)||(ch>255)) return false;
	return UniformKeySta[ch];
}
bool LeftClick, RightClick, MidClick;
int LeftUp, RightUp;
int LeftHold, RightHold;
double randf() {
	return double(rand()&32767)/32767.0;
}
#warning const
const int Garb=-0x888888, Solid=-0x555555, GarbZone=-0xFDD000, GarbRound=-0xCCCCCC, GarbLock=-0xFF6666, GarbBomb=-0xFFFF99, GarbQuest=-0x9E00FF;
const vector<int> C2ComboBase = {2440,1120,400,60,-160,-330,-470,-600,-710,-830,-940,-1050,-1160,-1260};
const vector<int> C2ComboBonus = {1220,610,300,180,120,90,70,50,40,30,30,20};
const vector<int> QPLevelScore =
{0, 50, 150, 300, 450, 650, 850, 1100, 1350, 1650,
2000, 2400, 2950, 3500, 4000, 4500, 5000, 5500, 6000, 6500,
7000, 7500, 8000, 8500, 9000, 9500, 10000, 11000, 12000, 15000};
const vector<int> LevelColor = {
0x666666,0xC23A30,0x006098,0xEE0000,0x008E9C,
0xA6217F,0xD29700,0xF6C582,0x009B6B,0x8FC13F,
0x009BC0,0xED796B,0x995D35,0xFFE211,0xD5A7A1,
0x5B2C68,0x76A32E,0x39C5BB,0x9999FF,0xEE82EE,
0x203864,0x73E9DB,0xFFCCCC,0x86001A,0xE40077,
0xE46022,0xB35A20,0xD97DAD,0x395C00,0xFF5353,
0xC6E002,0x999900,0x006666,0xFDD000,0xA29BBB,
0x0080FF,0x66CCFF,0xCB35BD,0x00DEB4,0xB9A567,
0xFFFFFF};
const vector<int> QPRiseTime = {8*60,8*60+2,10*60,10*60+2,10*60+4,12*60,12*60+2,12*60+4,12*60+8,12*60+10};
const vector<int> QPRevMod9RiseTime = {8*60,8*60+2,8*60+4,10*60,10*60+2,10*60+4,10*60+6,10*60+8,
12*60,12*60+2,12*60+4,12*60+6,12*60+8,12*60+10,12*60+12,12*60+14,12*60+16,12*60+18,12*60+20,12*60+22};
const vector<int> QPProtectDec = {4800,4800,3900,2100,1400,1300,900,600,400,300,200};
//const vector<int> QPProtectDec = {4800,4800,3900,2100,1400,1300,900,600};

const int BackgroundColor = 0x222222;
const int BoardColor = 0x333333;
const int ShadowColor = 0x666666;
const int GridColor=0x555555, OverGridColor=0x444444, RoundColor=0x777777, VanishColor=0x000033;

vector<pair<int,int> > RS, RS_I, RS_O, RS_C;

vector<Piece*> CustomPiece;

const Piece P_Empty;
const Piece P_Default(1, {{1}}, 0xBBBBBB, "*");

const Piece P_A(1, {{1}}, 0x228888, "A");

const Piece P_B(2, {{1,1}}, 0x89E5E5, "B"); 

const Piece P_C(2, {{1},{1,1}}, 0xFFAFBE, "C");
const Piece P_D(3, {{},{1,1,1}}, 0x00E5B7, "D");

const Piece P_I(4, {{},{1,1,1,1}}, 0x66CCFF, "I");
const Piece P_J(3, {{1},{1,1,1}}, 0x0080FF, "J");
const Piece P_L(3, {{0,0,1},{1,1,1}}, 0xFFA500, "L");
const Piece P_O(2, {{1,1},{1,1}}, 0xFFE211, "O");
const Piece P_S(3, {{0,1,1},{1,1}}, 0x2DD600, "S");
const Piece P_T(3, {{0,1,0},{1,1,1}}, 0xEE82EE, "T");
const Piece P_Z(3, {{1,1},{0,1,1}}, 0xEE3333, "Z");

const Piece P_I5(5, {{},{},{1,1,1,1,1}}, 0x66CCAA, "I5");
const Piece P_T5(3, {{0,1},{0,1},{1,1,1}}, 0xDF3782, "T5");
const Piece P_U(3, {{1,0,1},{1,1,1}}, 0xB17D43, "U");
const Piece P_V(3, {{1},{1},{1,1,1}}, 0x9E00FF, "V");
const Piece P_X(3, {{0,1},{1,1,1},{0,1}}, 0x9999FF, "X");
const Piece P_F(3, {{1},{1,1,1},{0,1}}, 0x00AAAA, "F");
const Piece P_E(3, {{0,0,1},{1,1,1},{0,1}}, 0xD29700, "E");
const Piece P_S5(3, {{1},{1,1,1},{0,0,1}}, 0x00AA00, "S5");
const Piece P_Z5(3, {{0,0,1},{1,1,1},{1}}, 0xAA0000, "Z5");
const Piece P_J5(4, {{},{1},{1,1,1,1}}, 0x6666FF, "J5");
const Piece P_L5(4, {{},{0,0,0,1},{1,1,1,1}}, 0xFF5000, "L5");
const Piece P_Y(4, {{},{0,0,1},{1,1,1,1}}, 0x00AAFF, "Y");
const Piece P_R(4, {{},{0,1},{1,1,1,1}}, 0xCC99FF, "R");
const Piece P_H(4, {{},{0,0,1,1},{1,1,1}}, 0x99E55B, "H");
const Piece P_N(4, {{},{1,1},{0,1,1,1}}, 0xFF6666, "N");
const Piece P_Q(3, {{0,1,1},{1,1,1}}, 0xCCCC00, "Q");
const Piece P_P(3, {{1,1},{1,1,1}}, 0xFDD000, "P");
const Piece P_W(3, {{1},{1,1},{0,1,1}}, 0x72752A, "W");

const Piece P_30(6, {{},{},{1,1,1,1,1,1}}, 0x96D6CB, "I6");
const Piece P_31(4, {{},{0,1,1},{1,1,1,1}}, 0x62FFE0, "B6");
const Piece P_32(3, {{0,1},{1,1,1},{1,1}}, 0xEB22B9, "A6");
const Piece P_33(3, {{1,1,1},{1,1,1}}, 0xCCCC99, "O6");
const Piece P_34(3, {{1},{1,1},{1,1,1}}, 0xC4A179, "E6");
const Piece P_35(4, {{0,0,0,1},{1,1,1,1},{0,0,0,1}}, 0x9A1751, "T6");
const Piece P_36(4, {{0,0,1},{1,1,1,1},{0,0,1}}, 0xD1D1FF, "X6");
const Piece P_37(3, {{0,1},{1,1,1},{1,0,1}}, 0x6F9B, "V6");
const Piece P_38(4, {{1,0,0,1},{1,1,1,1}}, 0xF3BDBD, "U6");
const Piece P_39(5, {{},{0,0,1},{1,1,1,1,1}}, 0x686998, "t6");
const Piece P_40(5, {{},{0,0,0,0,1},{1,1,1,1,1}}, 0xFFD17C, "L6");
const Piece P_41(5, {{},{1},{1,1,1,1,1}}, 0x48A4FF, "J6");
const Piece P_42(5, {{},{0,1},{1,1,1,1,1}}, 0xB59ECD, "Y6");
const Piece P_43(5, {{},{0,0,0,1},{1,1,1,1,1}}, 0x7ED0F8, "y6");
const Piece P_44(5, {{},{1,1},{0,1,1,1,1}}, 0xFF8F66, "N6");
const Piece P_45(5, {{},{0,0,0,1,1},{1,1,1,1}}, 0x7ECD3F, "n6");
const Piece P_46(4, {{1,1},{1,1,1,1}}, 0xCBB344, "P6");
const Piece P_47(4, {{0,0,1,1},{1,1,1,1}}, 0xDCE654, "Q6");
const Piece P_48(4, {{1,0,1},{1,1,1,1}}, 0x3A96B5, "F6");
const Piece P_49(4, {{0,1,0,1},{1,1,1,1}}, 0xE2B977, "f6");
const Piece P_50(4, {{0,0,0,1},{0,0,0,1},{1,1,1,1}}, 0xFFBF00, "V6");
const Piece P_51(4, {{1},{1},{1,1,1,1}}, 0x93B0CC, "v6");
const Piece P_52(4, {{0,1},{0,1},{1,1,1,1}}, 0xA879A7, "R6");
const Piece P_53(4, {{0,0,1},{0,0,1},{1,1,1,1}}, 0xC6F82F, "r6");
const Piece P_54(4, {{1},{1,1,1,1},{0,1}}, 0x1D9C58, "tf");
const Piece P_55(4, {{0,0,0,1},{1,1,1,1},{0,0,1}}, 0xED396F, "TF");
const Piece P_56(4, {{0,1},{1,1,1,1},{0,0,0,1}}, 0x8F9878, "lf");
const Piece P_57(4, {{0,0,1},{1,1,1,1},{1}}, 0x92837C, "LF");
const Piece P_58(4, {{1},{1,1,1,1},{0,0,0,1}}, 0x72FF72, "S6");
const Piece P_59(4, {{0,0,0,1},{1,1,1,1},{1}}, 0xFF9999, "Z6");
const Piece P_60(4, {{0,1},{1,1,1,1},{0,0,1}}, 0xE1CD68, "Xl");
const Piece P_61(4, {{0,0,1},{1,1,1,1},{0,1}}, 0x658666, "Xr");
const Piece P_62(4, {{0,0,1},{0,0,1,1},{1,1,1}}, 0x6B3131, "tv");
const Piece P_63(4, {{0,1},{1,1},{0,1,1,1}}, 0x6B5531, "TV");
const Piece P_64(4, {{},{0,1,1,1},{1,1,0,1}}, 0xD44AD6, "G6");
const Piece P_65(4, {{},{1,1,1},{1,0,1,1}}, 0xB56AFF, "g6");
const Piece P_66(5, {{},{1,1,1},{0,0,1,1,1}}, 0xA8C080, "z6");
const Piece P_67(5, {{},{0,0,1,1,1},{1,1,1}}, 0xA8C09F, "s6");
const Piece P_68(4, {{},{1,1,1},{0,1,1,1}}, 0x3B5224, "LZ");
const Piece P_69(4, {{},{0,1,1,1},{1,1,1}}, 0x334514, "LS");
const Piece P_70(4, {{0,0,1,1},{1,1,1},{0,0,1}}, 0x5F3C91, "GF");
const Piece P_71(4, {{1,1},{0,1,1,1},{0,1}}, 0x913C72, "GE");
const Piece P_72(3, {{1,1},{1,1,1},{1}}, 0x8CE7CC, "K6");
const Piece P_73(3, {{0,1,1},{1,1,1},{0,0,1}}, 0x96DCFF, "k6");
const Piece P_74(4, {{0,1},{1,1,1},{0,0,1,1}}, 0x5E91D8, "ZJ");
const Piece P_75(4, {{0,0,1},{0,1,1,1},{1,1}}, 0xCC5DE8, "SL");
const Piece P_76(4, {{1,1},{0,1},{0,1,1,1}}, 0x65CF70, "Zv");
const Piece P_77(4, {{0,0,1,1},{0,0,1},{1,1,1}}, 0x65B3CF, "Sv");
const Piece P_78(4, {{1},{1,1},{0,1,1,1}}, 0x6D6D14, "W6");
const Piece P_79(4, {{0,0,0,1},{0,0,1,1},{1,1,1}}, 0x84334B, "M6");
const Piece P_80(3, {{0,0,1},{1,0,1},{1,1,1}}, 0xA2FF00, "j6");
const Piece P_81(3, {{1},{1,0,1},{1,1,1}}, 0x1CFF18, "l6");
const Piece P_82(3, {{1},{1,1,1},{1,0,1}}, 0x18E0FF, "H6");
const Piece P_83(3, {{0,0,1},{1,1,1},{1,0,1}}, 0x5D54FF, "h6");
const Piece P_84(4, {{1},{1,1,1},{0,0,1,1}}, 0xBA4C4C, "w6");
const Piece P_85(4, {{0,0,0,1},{0,1,1,1},{1,1}}, 0xBAA147, "m6");
const Piece P_86(3, {{0,1,1},{1,1},{1,1}}, 0x7B60D3, "p6");
const Piece P_87(3, {{1,1},{0,1,1},{0,1,1}}, 0x60D395, "q6");
const Piece P_88(4, {{1,1},{0,1,1},{0,0,1,1}}, 0x834BEB, "MW");
const Piece P_89(4, {{0,0,1,1},{0,1,1},{1,1}}, 0xBC79B9, "WM");

const Piece P_MZ1(1, {{1}}, 0xEE0000, "Z-1");
const Piece P_ML1(3, {{},{1,1,1}}, 0xFFA500, "L-1");
const Piece P_MO1(2, {{1},{0,1}}, 0xFFE211, "O-1");
const Piece P_MS1(2, {{1,1},{1,0}}, 0x2DD600, "S-1");
const Piece P_MI1(5, {{},{},{1,1,1,1,1}}, 0x66CCFF, "I-1");
const Piece P_MJ1(3, {{1},{0,1,1}}, 0x0080FF, "J-1");
const Piece P_RMJ1(3, {{0,0,1},{1,1}}, 0xFFA500, "RJ-1");
const Piece P_MT1(3, {{0,1},{1,0,1}}, 0xEE82EE, "T-1");

const Piece P_MZ2(4, {{},{1,1},{0,0,1,1}}, 0xEE0000, "Z-2");
const Piece P_ML2(4, {{},{0,0,0,1},{1,1,1,1}}, 0xFFA500, "L-2");
const Piece P_MO2(3, {{1,0,1},{1,0,1}}, 0xFFE211, "O-2");
const Piece P_MS2(4, {{},{0,0,1,1},{1,1}}, 0x2DD600, "S-2");
const Piece P_MI2(5, {{},{},{1,1,1,0,1}}, 0x66CCFF, "I-2");
const Piece P_MJ2(4, {{},{1},{1,1,1,1}}, 0x0080FF, "J-2");
const Piece P_MT2(4, {{0,0,1,0},{1,1,1,1}}, 0xEE82EE, "T-2");

const Piece P_MZ3(5, {{},{1,1,1,1},{0,1,1,1,1}}, 0xEE0000, "Z-3");
const Piece P_ML3(4, {{},{0,0,0,1},{1,0,1,1}}, 0xFFA500, "L-3");
const Piece P_RML3(4, {{},{1},{1,1,0,1}}, 0x0080FF, "RL-3");
const Piece P_MO3(3, {{1,1,1},{1,1,1},{1,1,1}}, 0xFFE211, "O-3");
const Piece P_MS3(5, {{},{0,1,1,1,1},{1,1,1,1}}, 0x2DD600, "S-3");
const Piece P_MI3(4, {{},{1,1,1,1},{1,1,1,1}}, 0x66CCFF, "I-3");
const Piece P_MJ3(3, {{1},{1,1,1},{0,1}}, 0x0080FF, "J-3");
const Piece P_MT3(3, {{0,1},{0,1},{1,1,1}}, 0xEE82EE, "T-3");

const Piece P_MZ4(4, {{},{1,1,1,0},{0,0,1,1}}, 0xEE0000, "Z-4");
const Piece P_ML4(3, {{0,0,1},{0,0,1},{1,1,1}}, 0xFFA500, "L-4");
const Piece P_MO4(3, {{1,1},{1,1,1}}, 0xFFE211, "O-4");
const Piece P_MS4(4, {{},{0,1,1,1},{1,1}}, 0x2DD600, "S-4");
const Piece P_MI4(4, {{},{0,1},{1,0,1,1}}, 0x66CCFF, "I-4");
const Piece P_MJ4(3, {{1},{1},{0,1,1}}, 0x0080FF, "J-4");
const Piece P_MT4(3, {{0,1},{1,1,1},{1,0,1}}, 0xEE82EE, "T-4");

const Piece P_MZ5(3, {{1,1},{0,1},{0,1,1}}, 0xEE0000, "Z-5");
const Piece P_ML5(3, {{1,0,1},{1,1,1}}, 0xFFA500, "L-5");
const Piece P_MO5(3, {{0,1},{1,1,1},{1,1,1}}, 0xFFE211, "O-5");
const Piece P_MS5(3, {{0,1,1},{0,1},{1,1}}, 0x2DD600, "S-5");
const Piece P_MI5(5, {{},{0,0,0,0,1},{1,1,1,1}}, 0x66CCFF, "I-5");
const Piece P_MJ5(3, {{0,1},{1},{0,1,1}}, 0x0080FF, "J-5");
const Piece P_RMJ5(3, {{0,1},{0,0,1},{1,1}}, 0xFFA500, "RJ-5");
const Piece P_MT5(5, {{},{0,0,1},{1,1,1,1,1}}, 0xEE82EE, "T-5");

const Piece P_MZ6(4, {{},{1,0,1},{0,0,1,1}}, 0xEE0000, "Z-6");
const Piece P_RMZ6(4, {{},{0,1,0,1},{1,1}}, 0x2DD600, "RZ-6");
const Piece P_ML6(4, {{},{1,0,1},{1,1,1,1}}, 0xFFA500, "L-6");
const Piece P_MO6(3, {{0,1},{1,0,1},{0,1}}, 0xFFE211, "O-6");
const Piece P_MS6(3, {{0,1,1},{1,1},{1}}, 0x2DD600, "S-6");
const Piece P_MI6(4, {{1,1,1,1},{},{1,1,1,1}}, 0x66CCFF, "I-6");
const Piece P_MJ6(4, {{},{0,1,0,1},{1,1,1,1}}, 0x0080FF, "J-6");
const Piece P_MT6(4, {{0,0,1},{1,1,1,1},{1,1}}, 0xEE82EE, "T-6");

const Piece P_MZ7(4, {{1,1,1},{0,1,1},{0,1,1,1}}, 0xEE0000, "Z-7");
const Piece P_ML7(4, {{0,0,0,1},{1,1,1,1},{0,0,1}}, 0xFFA500, "L-7");
const Piece P_MO7(4, {{0,0,1},{1,1,1},{0,1,1,1},{0,1}}, 0xFFE211, "O-7");
const Piece P_RMO7(4, {{0,1,0},{0,1,1,1},{1,1,1},{0,0,1}}, 0xFFE211, "RO-7");
const Piece P_MS7(4, {{0,1,1,1},{0,1,1},{1,1,1}}, 0x2DD600, "S-7");
const Piece P_MI7(4, {{},{0,1,0,1},{1,0,1}}, 0x66CCFF, "I-7");
const Piece P_MJ7(4, {{},{1,0,0,1},{1,1,1,1}}, 0x0080FF, "J-7");
const Piece P_MT7(5, {{},{0,0,1},{0,1,1,1},{1,1,0,1,1}}, 0xEE82EE, "T-7");

const Piece P_MZ8(4, {{0,1,1},{0,0,1},{0,1},{0,1,1}}, 0xEE0000, "Z-8");
const Piece P_ML8(5, {{},{0,0,1,0,1},{1,1,0,1,1}}, 0xFFA500, "L-8");
const Piece P_MO8(4, {{0,1,1},{1,0,1},{1,0,1},{1,1}}, 0xFFE211, "O-8");
const Piece P_MS8(4, {{0,1,1},{0,1},{0,0,1},{0,1,1}}, 0x2DD600, "S-8");
const Piece P_MI8(4, {{1,0,0,1},{1,1,1,1},{1,0,0,1}}, 0x66CCFF, "I-8");
const Piece P_MJ8(5, {{},{1,0,1},{1,1,0,1,1}}, 0x0080FF, "J-8");
const Piece P_MT8(5, {{0,0,1},{0,1,1,1},{0,0,1},{0,1,1,1},{0,0,1}}, 0xEE82EE, "T-8");

const Piece P_MZ9(7, {{},{},{1,0,1,1},{0,0,0,1,1,0,1}}, 0xEE0000, "Z-9");
const Piece P_ML9(7, {{},{},{0,0,0,0,1,0,1},{1,0,1,1,1}}, 0xFFA500, "L-9");
const Piece P_MO9(6, {{0,0,1},{},{0,0,1,1},{0,0,1,1},{},{0,0,0,1}}, 0xFFE211, "O-9");
const Piece P_MS9(7, {{},{},{0,0,0,1,1,0,1},{1,0,1,1}}, 0x2DD600, "S-9");
const Piece P_MI9(7, {{1},{},{0,0,1},{},{0,0,0,0,1},{},{0,0,0,0,0,0,1}}, 0x66CCFF, "I-9");
const Piece P_MJ9(7, {{},{},{1,0,1},{0,0,1,1,1,0,1}}, 0x0080FF, "J-9");
const Piece P_MT9(6, {{0,0,1},{},{0,0,1},{0,1,1,1},{0},{0,0,1}}, 0xEE82EE, "T-9");

const Piece P_MZ10(6, {{0,0,1,1},{0,1,0,1,1},{0,0,0,1},{0,0,1},{0,1,1,0,1},{0,0,1,1}}, 0xEE0000, "Z-10");
const Piece P_ML10(6, {{},{0,0,0,0,1},{1,0,0,0,0,1},{1,1,1,1,1,1}}, 0xFFA500, "L-10");
const Piece P_MO10(6, {{0,0,1,1},{0,1,1,1,1},{1,1,0,0,1,1},{1,1,0,0,1,1},{0,1,1,1,1},{0,0,1,1}}, 0xFFE211, "O-10");
const Piece P_MS10(6, {{0,0,1,1},{0,1,1,0,1},{0,0,1},{0,0,0,1},{0,1,0,1,1},{0,0,1,1}}, 0x2DD600, "S-10");
const Piece P_MI10(7, {{},{},{0,1,1,1,1,0,1},{1,0,1,1,1,1}}, 0x66CCFF, "I-10");
const Piece P_MJ10(6, {{},{0,1},{1,0,0,0,0,1},{1,1,1,1,1,1}}, 0x0080FF, "J-10");
const Piece P_MT10(5, {{1,1,1,1,1},{1,0,1,0,1},{0,0,1},{0,0,1},{0,1,1,1}}, 0xEE82EE, "T-10");

const Piece P_Bag3(1, {{1}}, 0xBBBBBB, "Bag3");
const Piece P_Bag4(1, {{1}}, 0xBBBBBB, "Bag4");
const Piece P_Bag5(1, {{1}}, 0xBBBBBB, "Bag5");
const Piece P_Bag6(1, {{1}}, 0xBBBBBB, "Bag6");

const vector<Piece> QPModM_I = {P_MI1,P_MI2,P_MI3,P_MI4,P_MI5,P_MI6,P_MI7,P_MI8,P_MI9,P_MI10};
const vector<Piece> QPModM_J = {P_MJ1,P_MJ2,P_MJ3,P_MJ4,P_MJ5,P_MJ6,P_MJ7,P_MJ8,P_MJ9,P_MJ10};
const vector<Piece> QPModM_L = {P_ML1,P_ML2,P_ML3,P_ML4,P_ML5,P_ML6,P_ML7,P_ML8,P_ML9,P_ML10};
const vector<Piece> QPModM_O = {P_MO1,P_MO2,P_MO3,P_MO4,P_MO5,P_MO6,P_MO7,P_MO8,P_MO9,P_MO10};
const vector<Piece> QPModM_S = {P_MS1,P_MS2,P_MS3,P_MS4,P_MS5,P_MS6,P_MS7,P_MS8,P_MS9,P_MS10};
const vector<Piece> QPModM_T = {P_MT1,P_MT2,P_MT3,P_MT4,P_MT5,P_MT6,P_MT7,P_MT8,P_MT9,P_MT10};
const vector<Piece> QPModM_Z = {P_MZ1,P_MZ2,P_MZ3,P_MZ4,P_MZ5,P_MZ6,P_MZ7,P_MZ8,P_MZ9,P_MZ10};

const Piece P_B02(3, {{0},{1,0,1}}, 0x89E5E5, "B02");
const Piece P_B03(4, {{0},{1,0,0,1}}, 0x89E5E5, "B03");
const Piece P_B04(5, {{0},{0},{1,0,0,0,1}}, 0x89E5E5, "B04");
const Piece P_B05(6, {{0},{0},{1,0,0,0,0,1}}, 0x89E5E5, "B05");
const Piece P_B11(2, {{1},{0,1}}, 0x89E5E5, "B11");
const Piece P_B12(3, {{1},{0,0,1}}, 0x89E5E5, "B12");
const Piece P_B13(4, {{0},{1},{0,0,0,1}}, 0x89E5E5, "B13");
const Piece P_B14(5, {{0},{1},{0,0,0,0,1}}, 0x89E5E5, "B14");
const Piece P_B15(6, {{0},{0},{1},{0,0,0,0,0,1}}, 0x89E5E5, "B15");
const Piece P_B22(3, {{1},{0},{0,0,1}}, 0x89E5E5, "B22");
const Piece P_B23(4, {{1},{0},{0,0,0,1}}, 0x89E5E5, "B23");
const Piece P_B24(5, {{0},{1},{0},{0,0,0,0,1}}, 0x89E5E5, "B24");
const Piece P_B25(6, {{0},{1},{0},{0,0,0,0,0,1}}, 0x89E5E5, "B25");
const Piece P_B33(4, {{1},{0},{0},{0,0,0,1}}, 0x89E5E5, "B33");
const Piece P_B34(5, {{1},{0},{0},{0,0,0,0,1}}, 0x89E5E5, "B34");
const Piece P_B35(6, {{0},{1},{0},{0},{0,0,0,0,0,1}}, 0x89E5E5, "B35");
const Piece P_B44(5, {{1},{0},{0},{0},{0,0,0,0,1}}, 0x89E5E5, "B44");
const Piece P_B45(6, {{1},{0},{0},{0},{0,0,0,0,0,1}}, 0x89E5E5, "B45");
const Piece P_B55(6, {{1},{0},{0},{0},{0},{0,0,0,0,0,1}}, 0x89E5E5, "B55");

const vector<Piece> HomePool = {P_I,P_J,P_L,P_O,P_S,P_T,P_Z};
/*{P_A,P_B,P_C,P_D,P_I,P_J,P_L,P_O,P_S,P_T,P_Z,
P_I5,P_T5,P_U,P_V,P_X,P_F,P_E,P_S5,P_Z5,P_J5,
P_L5,P_Y,P_R,P_H,P_N,P_Q,P_P,P_W};*/
const vector<Piece> PieceList = {P_Empty,P_Empty,P_A,P_Empty,P_B,P_Empty,P_Bag3,P_C,P_D,P_Empty,
P_Bag4,P_I,P_J,P_L,P_O,P_S,P_T,P_Z,P_Empty,P_Empty,
P_Bag5,P_I5,P_T5,P_U,P_V,P_X,P_F,P_E,P_S5,P_Z5,P_J5,
P_L5,P_Y,P_R,P_H,P_N,P_Q,P_P,P_W,P_Bag6,
P_30,P_31,P_32,P_33,P_34,P_35,P_36,P_37,P_38,P_39,
P_40,P_41,P_42,P_43,P_44,P_45,P_46,P_47,P_48,P_49,
P_50,P_51,P_52,P_53,P_54,P_55,P_56,P_57,P_58,P_59,
P_60,P_61,P_62,P_63,P_64,P_65,P_66,P_67,P_68,P_69,
P_70,P_71,P_72,P_73,P_74,P_75,P_76,P_77,P_78,P_79,
P_80,P_81,P_82,P_83,P_84,P_85,P_86,P_87,P_88,P_89};

const Piece P_Garbage(1, {{1}}, Garb, "G");
const vector<Piece> TetraminoPool = {P_I,P_J,P_L,P_O,P_S,P_T,P_Z};
const vector<Piece> PentominoPool = {P_I5,P_T5,P_U,P_V,P_X,P_F,P_E,P_S5,P_Z5,P_J5,P_L5,P_Y,P_R,P_H,P_N,P_Q,P_P,P_W};
const vector<Piece> HexaminoPool = {P_30,P_31,P_32,P_33,P_34,P_35,P_36,P_37,P_38,P_39,P_40,P_41,P_42,P_43,P_44,P_45,P_46,P_47,P_48,P_49,P_50,P_51,P_52,P_53,P_54,P_55,P_56,P_57,P_58,P_59,P_60,P_61,P_62,P_63,P_64,P_65,P_66,P_67,P_68,P_69,P_70,P_71,P_72,P_73,P_74,P_75,P_76,P_77,P_78,P_79,P_80,P_81,P_82,P_83,P_84,P_85,P_86,P_87,P_88,P_89}; 
const vector<Piece> DefaultPool = TetraminoPool;

vector<Piece> CustomPiecePrototypes;

//const vector<Piece> DefaultPool = {P_A,P_B,P_C,P_D};
//const vector<Piece> DefaultPool = {P_A,P_B,P_C,P_D,P_I,P_J,P_L,P_O,P_S,P_T,P_Z,P_I5,P_T5,P_U,P_V,P_X,P_F,P_E,P_S5,P_Z5,P_J5,P_L5,P_Y,P_R,P_H,P_N,P_Q,P_P,P_W};
enum EGenerationType {
	G_Random, G_Bag, G_Fixed
};
enum EBlockStyle {
	S_Default, S_Active, S_Garbage, S_Simple
};
enum EBaseRule {
	BSR_Default, BSR_Equal, BSR_Classic, BSR_ASC, BSR_Arcade, BSR_None
};
enum EComboRule {
	CR_Default, CR_Guildline, CR_Techmino, CR_Friends, CR_Expert, CR_Battle,
	CR_99, CR_PPT, CR_Effect, CR_Zone, CR_C2, CR_Classic, CR_Arcade, CR_None
};
enum EClutchRule {
	CLR_Default, CLR_None, CLR_Always
};
enum ESpinRule {
	SR_Default, SR_AllMini, SR_Guildline, SR_AllSpin, SR_AllSemi, SR_IO, SR_Easy, SR_None
};
enum EB2BRule {
	BR_Guildline, BR_Chain, BR_Surge, BR_QP, BR_Techmino, BR_None
};
enum EAllClearRule {
	AR_Default, AR_IO, AR_Guildline, AR_QP, AR_Techmino, AR_Arcade, AR_None
};
enum EIntRule {
	IR_Floor, IR_Accumulate, IR_Random, IR_Ceil
};
enum ERotateSystem {
	R_Default, R_SRSPlus, R_StrictSRSPlus, R_ASCDX, R_ASC,
	R_LNRS, R_RNRS, R_ARS, R_C2, R_Sega, R_New,
	R_DX, R_Atari, R_TetraX, R_Zhoumetry, R_None
};
enum ELevScaleMode {
	LS_Default, LS_Div, LS_Dec, LS_Exp
};
enum EGarbageShape {
	GS_Default, GS_Full, GS_Empty, GS_Bubble, GS_Random, GS_Board, GS_Stair, GS_Copy
};
enum EGarbageType {
	GT_Default, GT_Solid, GT_Lock, GT_Bomb, GT_Bricks
};
enum EGarbageActive {
	GA_Default, GA_Attack, GA_None, GA_Instant
};
enum EGravityType {
	GV_Default, GV_Cascade, GV_None, GV_Sticky, GV_Color, GV_Separate, GV_Avalanche, GV_Fall
};
enum ETargetType {
	TT_None, TT_All, TT_Even, TT_Elimination, TT_Random, TT_Payback, TT_Badges, TT_Attackers, TT_Backfire
};
#warning enum
class PieceGenerator {
	vector<int> His;
	mt19937 rng;
	EGenerationType Type;
	int H, R, E;
	public :
	vector<Piece> Pool;
	vector<Piece> RemPool;
	PieceGenerator(vector<Piece> _Pool=DefaultPool, EGenerationType _Type=G_Bag, int Seed=0, int _H=0, int _R=0, int _E=0) {
		rng = mt19937(Seed);
		Pool = _Pool;
		Type = _Type;
		H=_H; R=_R; E=_E;
	}
	Piece Roll() {
		int n = Pool.size();
		if (!n) return P_Default;
		if (Type==G_Random) {
			RemPool.clear();
			int r = rng()%n;
			for (int i=0; i<R; ++i) {
				bool f = false;
				for (int j : His) {
					if (r==j) f=true;
				}
				if (f) r=rng()%n;
				else break;
			}
			His.push_back(r);
			while (His.size()>H) {
				for (int i=1; i<His.size(); ++i) His[i-1]=His[i];
				His.pop_back();
			}
			return Pool[r];
		}
		if (Type==G_Bag) {
			if (RemPool.empty()) {
				int cnt=E/n+1, rem=E%n;
				if (rem) {
					RemPool=Pool; shuffle(RemPool.begin(),RemPool.end(),rng);
					RemPool.resize(rem);
				}
				for (int i=1; i<=cnt; ++i) {
					for (Piece x : Pool) RemPool.push_back(x);
				}
			}
			int m=RemPool.size(), pos=rng()%m;
			Piece res=RemPool[pos]; swap(RemPool[pos],RemPool[m-1]);
			RemPool.pop_back();
			return res;
		}
		if (Type==G_Fixed) {
			if (RemPool.empty()) {
				RemPool=Pool; reverse(RemPool.begin(),RemPool.end());
			}
			Piece res = RemPool.back();
			RemPool.pop_back(); return res;
		}
		return P_Default;
	}
};
enum Action {
	A_Left, A_Right, A_SoftDrop, A_HardDrop, A_SonicDrop,
	A_Rotate, A_CW, A_CCW, A_Half, A_Hold, A_Retry,
	A_Pause, A_Click, A_RightClick, A_MidClick, A_Quit,
	A_Up, A_Flip, A_Waste, A_Reset, A_Lock,
	A_CursorMode, A_TargetMode, A_Undo, A_Redo, A_Action
};
const vector<pair<string,Action> > KeyToAct = {{"KeyLeft",A_Left},
{"KeyRight",A_Right},
{"KeySoft",A_SoftDrop},
{"KeyHard",A_HardDrop},
{"KeySonic",A_SonicDrop},
{"KeyRotate",A_Rotate},
{"KeyCW",A_CW},
{"KeyCCW",A_CCW},
{"KeyHalf",A_Half},
{"KeyHold",A_Hold},
{"KeyRetry",A_Retry},
{"KeyPause",A_Pause},
{"KeyUp",A_Up},
{"KeyReset",A_Reset},
{"KeyFlip",A_Flip},
{"KeyWaste",A_Waste},
{"KeyCursorMode",A_CursorMode},
{"KeyTargetMode",A_TargetMode},
{"KeyUndo",A_Undo},
{"KeyRedo",A_Redo},
{"KeyAction",A_Action}};
class Monitor {
	bool Sta; int KeyDownTime, IgnoredTime;
	public :
	int DAS, ARR, DCD; Monitor *Opposite;
	int Key, DCDRem; bool Enabled, DASEnable;
	Action Result;
	Monitor(Action _Action, int _Key=0, bool _Enabled=true, int _DAS=-1, int _ARR=-1, int _DCD=0) {
		Result = _Action;
		Key=_Key; Enabled=_Enabled; DAS=_DAS; ARR=_ARR;
		DCD=_DCD; Opposite=nullptr;
		Sta=DASEnable=false; KeyDownTime=IgnoredTime=DCDRem=0;
	}
	int Output(int TimeDel, bool Ignore=false) {
		bool NewSta = ((CheckKey(Key))&&(Enabled));
		if (!NewSta) DCDRem=0;
		else if ((Opposite>=0)&&(DCD>0)&&((Opposite!=nullptr)&&((Opposite->Sta)&&(!Opposite->DASEnable)))) DCDRem=DCD;
		else DCDRem=max(0,DCDRem-TimeDel);
		if (DCDRem) Ignore=true;
		int res = 0;
		if (!NewSta) {
			DASEnable=false; KeyDownTime=IgnoredTime=0;
		}
		else if (Ignore) {
			NewSta=Sta; IgnoredTime+=TimeDel;
		}
		else if (NewSta) {
			KeyDownTime += TimeDel;
			if (IgnoredTime) {
				KeyDownTime+=IgnoredTime; IgnoredTime=0;
				if (DASEnable) KeyDownTime=min(KeyDownTime,max(0,ARR));
				else KeyDownTime=min(KeyDownTime,max(0,DAS));
			}
			if (!DAS) DASEnable=true;
			if ((!Sta)&&(!DASEnable)) res=1;
			else {
				if (DASEnable) {
					if ((ARR>=0)&&(KeyDownTime>=ARR)) {
						res=1; KeyDownTime=min(max(0,KeyDownTime-ARR),ARR+5000);
					}
				}
				else if ((DAS>=0)&&(KeyDownTime>=DAS)) {
					res=1; DASEnable=true;
					KeyDownTime = min(max(0,KeyDownTime-DAS),DAS+5000);
				}
			}
		}
		if (!Ignore) IgnoredTime=0;
		Sta = NewSta;
		return res;
	}
	bool CheckDAS() {
		return DASEnable;
	}
};

const vector<ConfigContent> HomeConfig =
{{"StartDelay",0},{"Stock",-1},{"Bot",1},{"BotType",6},{"BotSpeed",300},{"LCD",300},{"LockDelay",2000},{"ResetLim",9999999},{"AutoRespawn",1},{"HideStat",1},{"UseClick",0},{"RotateSystem",R_SRSPlus}};
const vector<ConfigContent> SettingConfig =
{{"StartDelay",0},{"Stock",-1},{"UseUp",1},{"UseZone",1},{"UseFlip",1},{"UseWaste",1},{"UseUndo",1},{"UseLock",1},{"UsePlace",1},{"HideStat",1},{"AutoRespawn",1},{"ResetLim",9999999},{"DropDelay",-1},{"LockDelay",-1},{"HoldType",2}};
const vector<ConfigContent> SelectConfig = {{"Player",0}};
vector<pair<int,int> > ASC_CW, ASC_CCW={{0,0},{1,0},{0,-1},{1,-1},{0,-2},{1,-2},{2,0},{2,-1},{2,-2},{-1,0},{-1,-1},{0,1},{1,1},{2,1},{-1,-2},{-2,0},{0,2},{1,2},{2,2},{-2,-1},{-2,-2},{-1,1}};
vector<pair<int,int> > SRS[4][4], SRS_I[4][4];
vector<pair<int,int> > DefRot[4][4], DefRot_I[4][4], DefRot_O[4][4], ASCDX_O[4][4];
vector<pair<int,int> > SRS_C[4][4], DefRot_C[4][4];
vector<pair<int,int> > None = {{0,0}};
vector<pair<int,int> > ASCDX_CCW, ASCDX_CW, ASCDX_FLIP, ASCDX_RFLIP;
vector<pair<int,int> > DefRot_CCW, DefRot_CW, DefRot_FLIP, DefRot_RFLIP;
vector<pair<int,int> > C2;
vector<pair<int,int> > TX[4][4], TX_I[4][4];
void InitKick() {
	SRS[0][3]={{0,0},{-1,0},{-1,+1},{0,-2},{-1,-2},{-1,-1},{0,+1},{0,-1}};
	SRS[3][0]={{0,0},{+1,0},{+1,-1},{0,+2},{+1,+2},{+1,+1},{0,-1},{0,+1}};
	SRS[3][2]={{0,0},{+1,0},{+1,-1},{0,+2},{+1,+2},{+1,+1},{0,-1},{0,+1}};
	SRS[2][3]={{0,0},{-1,0},{-1,+1},{0,-2},{-1,-2},{-1,-1},{0,+1},{0,-1}};
	SRS[2][1]={{0,0},{+1,0},{+1,+1},{0,-2},{+1,-2},{+1,-1},{0,+1},{0,-1}};
	SRS[1][2]={{0,0},{-1,0},{-1,-1},{0,+2},{-1,+2},{-1,+1},{0,-1},{0,+1}};
	SRS[1][0]={{0,0},{-1,0},{-1,-1},{0,+2},{-1,+2},{-1,+1},{0,-1},{0,+1}};
	SRS[0][1]={{0,0},{+1,0},{+1,+1},{0,-2},{+1,-2},{+1,-1},{0,+1},{0,-1}};
	SRS[0][2]={{0,0},{0,+1},{+1,+1},{-1,+1},{+1,0},{-1,0}};
	SRS[2][0]={{0,0},{0,-1},{-1,-1},{+1,-1},{-1,0},{+1,0}};
	SRS[1][3]={{0,0},{-1,0},{-1,+2},{-1,+1},{0,+2},{0,+1}};
	SRS[3][1]={{0,0},{+1,0},{+1,+2},{+1,+1},{0,+2},{0,+1}};
	/*SRS_I[0][3]={{0,0},{-2,0},{+1,0},{-2,-1},{+1,+2}};
	SRS_I[3][0]={{0,0},{+2,0},{-1,0},{+2,+1},{-1,-2}};
	SRS_I[3][2]={{0,0},{-1,0},{+2,0},{-1,+2},{+2,-1}};
	SRS_I[2][3]={{0,0},{+1,0},{-2,0},{+1,-2},{-2,+1}};
	SRS_I[2][1]={{0,0},{+2,0},{-1,0},{+2,+1},{-1,-2}};
	SRS_I[1][2]={{0,0},{-2,0},{+1,0},{-2,-1},{+1,+2}};
	SRS_I[1][0]={{0,0},{+1,0},{-2,0},{+1,-2},{-2,+1}};
	SRS_I[0][1]={{0,0},{-1,0},{+2,0},{-1,+2},{+2,-1}};
	SRS_I[0][2]={{0,0},{0,+1},{+1,+1},{-1,+1},{+1,0},{-1,0}};
	SRS_I[2][0]={{0,0},{0,-1},{-1,-1},{+1,-1},{-1,0},{+1,0}};
	SRS_I[1][3]={{0,0},{-1,0},{-1,+2},{-1,+1},{0,+2},{0,+1}};
	SRS_I[3][1]={{0,0},{+1,0},{+1,+2},{+1,+1},{0,+2},{0,+1}};*/
	SRS_I[0][3]={{0,0},{+1,0},{-2,0},{-2,-1},{+1,+2}};
	SRS_I[3][0]={{0,0},{-1,0},{+2,0},{-1,-2},{+2,+1}};
	SRS_I[3][2]={{0,0},{-1,0},{+2,0},{-1,+2},{+2,-1}};
	SRS_I[2][3]={{0,0},{-2,0},{+1,0},{-2,+1},{+1,-2}};
	SRS_I[2][1]={{0,0},{+2,0},{-1,0},{+2,+1},{-1,-2}};
	SRS_I[1][2]={{0,0},{+1,0},{-2,0},{+1,+2},{-2,-1}};
	SRS_I[1][0]={{0,0},{+1,0},{-2,0},{+1,-2},{-2,+1}};
	SRS_I[0][1]={{0,0},{-1,0},{+2,0},{+2,-1},{-1,+2}};
	SRS_I[0][2]={{0,0},{0,+1},{+1,+1},{-1,+1},{+1,0},{-1,0}};
	SRS_I[2][0]={{0,0},{0,-1},{-1,-1},{+1,-1},{-1,0},{+1,0}};
	SRS_I[1][3]={{0,0},{-1,0},{-1,+2},{-1,+1},{0,+2},{0,+1}};
	SRS_I[3][1]={{0,0},{+1,0},{+1,+2},{+1,+1},{0,+2},{0,+1}};
	// DefRot
	SRS_C[0][1]={{0,0},{-1,0},{+1,0},{-2,0},{+2,0}};
	SRS_C[1][0]={{0,0},{+1,0},{-1,0},{+2,0},{-2,0}};
	SRS_C[3][2]={{0,0},{-1,0},{+1,0},{-2,0},{+2,0}};
	SRS_C[2][3]={{0,0},{+1,0},{-1,0},{+2,0},{-2,0}};
	SRS_C[3][0]={{0,0},{+1,0},{-1,0},{0,-1},{0,+1}};
	SRS_C[0][3]={{0,0},{-1,0},{+1,0},{0,+1},{0,-1}};
	SRS_C[2][1]={{0,0},{-1,0},{+1,0},{0,-1},{0,+1}};
	SRS_C[1][2]={{0,0},{+1,0},{-1,0},{0,+1},{0,-1}};
	SRS_C[3][1]={{0,0},{-1,0},{-1,+1},{0,+1},{+1,+1}};
	SRS_C[1][3]={{0,0},{+1,0},{+1,-1},{0,-1},{-1,-1}};
	SRS_C[2][0]={{0,0},{+1,0},{+1,+1},{0,+1},{-1,+1}};
	SRS_C[0][2]={{0,0},{-1,0},{-1,-1},{0,-1},{+1,-1}};
	for (int i=0; i<4; ++i) {
		for (int j=0; j<4; ++j) {
			DefRot[i][j]=SRS[i][j]; DefRot_I[i][j]=SRS_I[i][j]; DefRot_C[i][j]=SRS_C[i][j];
			if ((i&1)!=(j&1)) {
				while (SRS[i][j].size()>5) SRS[i][j].pop_back();
			}
		}
	}
	for (pair<int,int> o : ASC_CCW) ASC_CW.push_back(make_pair(-o.first,o.second));
	vector<pair<int,int> > CCW, CW, FLIP, RFLIP;
	CCW = {{0,0},{0,-1},{1,0},{1,-1},{0,-2},{1,-2},{0,-3},{2,0},{2,-1},{3,0},{3,-1},{2,-2},{1,-3},{3,-2},{2,-3},{3,-3}, // 15
	{-1,0},{-1,-1},{0,1},{1,1},{2,1},{-1,-2},{3,1},{-1,-3},{-2,0},{0,2},{1,2},{2,2},{3,2},{-2,-1},{-2,-2},//30
	{-1,1},{-2,-2},{1,3},{2,3},{3,3},{-3,-1},{-3,-2},{-3,-3},{-2,1},{-1,2},{-2,2},{-3,0},{0,3},{-3,1},{-1,3},{-3,2},{-2,3},{-3,3}};
	/*
	35 34 33 43 45 47 48
	28 27 26 25 40 41 46
	22 20 19 18 31 39 44
	_9 _7 _1 _0 16 24 42
	10 _8 _3 _2 17 29 36
	13 11 _5 _4 21 30 37
	15 14 12 _6 23 32 38
	*/
	for (pair<int,int> p : CCW) CW.push_back(make_pair(-p.first,p.second));
	for (int i=0; i<CW.size(); ++i) {
		bool ok = true;
		for (int j=0; j<FLIP.size(); ++j) {
			if (FLIP[j]==CCW[i]) ok=false;
		}
		if (ok) FLIP.push_back(CCW[i]);
		ok = true;
		for (int j=0; j<FLIP.size(); ++j) {
			if (FLIP[j]==CW[i]) ok=false;
		}
		if (ok) FLIP.push_back(CW[i]);
	}
	for (pair<int,int> p : FLIP) RFLIP.push_back(make_pair(-p.first,p.second));
	ASCDX_CCW=CCW; ASCDX_CW=CW;
	ASCDX_FLIP=FLIP; ASCDX_RFLIP=RFLIP;
	stable_sort(CCW.begin(), CCW.end(), [](pair<int,int> x, pair<int,int> y) {
		return x.first*x.first+x.second*x.second<y.first*y.first+y.second*y.second;
	});
	stable_sort(CW.begin(), CW.end(), [](pair<int,int> x, pair<int,int> y) {
		return x.first*x.first+x.second*x.second<y.first*y.first+y.second*y.second;
	});
	stable_sort(FLIP.begin(), FLIP.end(), [](pair<int,int> x, pair<int,int> y) {
		return x.first*x.first+x.second*x.second<y.first*y.first+y.second*y.second;
	});
	stable_sort(RFLIP.begin(), RFLIP.end(), [](pair<int,int> x, pair<int,int> y) {
		return x.first*x.first+x.second*x.second<y.first*y.first+y.second*y.second;
	});
	DefRot_CCW=CCW; DefRot_CW=CW;
	DefRot_FLIP=FLIP; DefRot_RFLIP=RFLIP;
	DefRot[0][2] = {{0,0},{+1,0},{+2,0},{0,-1},{+1,-1},{+2,-1},{-1,0},{-2,0},{-1,-1},{-2,-1},{+3,0},{-3,0}};
	DefRot[3][1] = {{0,0},{0,-1},{0,-2},{-1,-1},{-1,-2},{0,-1},{+1,0},{0,-3},{-1,0}};
	DefRot[2][0] = {{0,0},{0,-1},{-1,0},{-2,0},{0,+1},{+1,0},{+2,0},{-3,0},{+3,0},{0,+1}};
	DefRot[1][3] = {{0,0},{0,-1},{0,-2},{+1,-1},{+1,-2},{0,-1},{-1,0},{0,-3},{+1,0}};
	for (int i=0; i<4; ++i) {
		DefRot_I[i][(i+2)&3] = DefRot[i][(i+2)&3];
		DefRot_C[i][(i+2)&3] = DefRot[i][(i+2)&3];
	}
	for (int i=0; i<4; ++i) {
		for (int j=0; j<4; ++j) {
			vector<pair<int,int> > NK;
			if (j==((i+1)&3)) NK=CCW;
			if (j==((i+2)&3)) NK=(i<2)?FLIP:RFLIP;
			if (j==((i+3)&3)) NK=CW;
			for (pair<int,int> _gg : NK) {
				bool ok = true;
				pair<int,int> gg = _gg;
				/*if ((i&1)!=(j&1)) {
					if ((i==3)||(j==3)) gg.first=-gg.first;
					if (i&1) {
						gg.first=-gg.first; gg.second=-gg.second;
					}
					if (((i+3)&3)==j) gg.first=-gg.first;
				}*/
				for (pair<int,int> hh : DefRot[i][j]) {
					if (gg==hh) ok=false;
				}
				if (ok) DefRot[i][j].push_back(gg);
				ok = true;
				for (pair<int,int> hh : DefRot_I[i][j]) {
					if (gg==hh) ok=false;
				}
				if (ok) DefRot_I[i][j].push_back(gg);
				ok = true;
				for (pair<int,int> hh : DefRot_C[i][j]) {
					if (gg==hh) ok=false;
				}
				if (ok) DefRot_C[i][j].push_back(gg);
			}
		}
	}
	for (int i=0; i<4; ++i) {
		for (int j=0; j<4; ++j) DefRot_O[i][j]=ASCDX_O[i][j]={{0,0}};
	}
	vector<pair<int,int> > tmp;
	for (int i=1; i<=3; ++i) {
		tmp.push_back({0,-i});
		for (int j=1; j<=1; ++j) {
			tmp.push_back({j,-i}); tmp.push_back({-j,-i});
		}
	}
	tmp.push_back({0,0});
	DefRot_O[2][0] = tmp;
	tmp.clear();
	for (int i=1; i<=3; ++i) {
		tmp.push_back({-i,0});
		for (int j=1; j<=1; ++j) {
			tmp.push_back({-i,j}); tmp.push_back({-i,-j});
		}
	}
	tmp.push_back({0,0});
	DefRot_O[1][3] = tmp;
	tmp.clear();
	for (int i=1; i<=3; ++i) {
		tmp.push_back({i,0});
		for (int j=1; j<=1; ++j) {
			tmp.push_back({i,j}); tmp.push_back({i,-j});
		}
	}
	tmp.push_back({0,0});
	DefRot_O[3][1] = tmp;
	tmp.clear();
	for (int i=1; i<=5; ++i) {
		tmp.push_back({0,-i});
		for (int j=1; j<=min(i,1); ++j) {
			tmp.push_back({j,-i}); tmp.push_back({-j,-i});
		}
	}
	for (int i=1; i<=5; ++i) {
		tmp.push_back({0,-i});
		for (int j=min(i,1)+1; j<=3; ++j) {
			tmp.push_back({j,-i}); tmp.push_back({-j,-i});
		}
	}
	tmp.push_back({0,0});
	ASCDX_O[2][0] = tmp;
	tmp.clear();
	for (int i=1; i<=5; ++i) {
		tmp.push_back({-i,0});
		for (int j=1; j<=min(i,1); ++j) {
			tmp.push_back({-i,j}); tmp.push_back({-i,-j});
		}
	}
	for (int i=1; i<=5; ++i) {
		tmp.push_back({-i,0});
		for (int j=min(i,1)+1; j<=3; ++j) {
			tmp.push_back({-i,j}); tmp.push_back({-i,-j});
		}
	}
	tmp.push_back({0,0});
	ASCDX_O[1][3] = tmp;
	tmp.clear();
	for (int i=1; i<=5; ++i) {
		tmp.push_back({i,0});
		for (int j=1; j<=min(i,1); ++j) {
			tmp.push_back({i,j}); tmp.push_back({i,-j});
		}
	}
	for (int i=1; i<=5; ++i) {
		tmp.push_back({i,0});
		for (int j=min(i,1)+1; j<=3; ++j) {
			tmp.push_back({i,j}); tmp.push_back({i,-j});
		}
	}
	tmp.push_back({0,0});
	ASCDX_O[3][1] = tmp;
	// C2
	C2 = {{0,0},{-1,0},{+1,0},{0,-1},{-1,-1},{+1,-1},{-2,0},{+2,0}};
	// TetraX
	for (int i=0; i<4; ++i) {
		for (int j=0; j<4; ++j) {
			if (((i+2)&3)==j) TX[i][j]={{0,0},{0,+1},{0,-1},{-1,0},{+1,0}};
			else if (((i+3)&3)==j) TX[i][j]={{0,0},{0,+1},{-1,0},{+1,0},{-1,+1},{+1,+1},{0,-1},{-1,-1},{+1,-1}};
			else if (((i+1)&3)==j) TX[i][j]={{0,0},{0,+1},{+1,0},{-1,0},{+1,+1},{-1,+1},{0,-1},{+1,-1},{-1,-1}};
		}
	}
	TX_I[0][3] = {{0,0},{0,-1},{0,-2},{0,+1},{+1,-1},{-1,-1},{+1,-2},{-1,-2}};
	TX_I[3][0]=TX_I[3][2]={{0,0},{0,-1},{0,-2},{0,+1},{-1,0},{+1,0},{+2,0}};
	TX_I[2][3] = {{0,0},{0,+1},{0,+2},{0,-1},{-1,+1},{+1,+1},{-1,+2},{+1,+2}};
	TX_I[2][1] = {{0,0},{0,+1},{0,+2},{0,-1},{+1,+1},{-1,+1},{+1,+2},{-1,+2}};
	TX_I[1][2]=TX_I[1][0]={{0,0},{0,-1},{0,-2},{0,-1},{+1,0},{-1,0},{-2,0}};
	TX_I[0][1] = {{0,0},{0,-1},{0,-2},{0,+1},{-1,-1},{+1,-1},{-1,-2},{+1,-2}};
}
vector<string> LineClearWord;
void InitText() {
	LineClearWord.resize(27); LineClearWord[0]="VOID";
	LineClearWord[1]="SINGLE"; LineClearWord[2]="DOUBLE"; LineClearWord[3]="TRIPLE"; LineClearWord[4]="QUAD";
	LineClearWord[5]="PENTA"; LineClearWord[6]="HEXA"; LineClearWord[7]="HEPTA"; LineClearWord[8]="OCTA";
	LineClearWord[9]="ENNEA"; LineClearWord[10]="DECA"; LineClearWord[11]="HENDECA"; LineClearWord[12]="DODECA";
	LineClearWord[13]="TRIADECA"; LineClearWord[14]="TESSARADECA"; LineClearWord[15]="PENTEDECA"; LineClearWord[16]="HEXADECA";
	LineClearWord[17]="HEPTADECA"; LineClearWord[18]="OCTADECA"; LineClearWord[19]="ENNEADECA"; LineClearWord[20]="EICOSA";
	LineClearWord[21]="ULTIMATRIS"; LineClearWord[22]="KIRBTRIS"; LineClearWord[23]="INFINITRIS"; LineClearWord[24]="KAGARIS"; LineClearWord[25]="ELECTRIS";
	LineClearWord[26] = "PERFECTRIS";
}
void InitChar() {
	Char['0'] = {"fbdj375zf","zj"};
	Char['1'] = {"kc6","48"};
	Char['2'] = {"fbdjo483"};
	Char['3'] = {"fbdjosy374","qs"};
	Char['4'] = {"7dckuy"};
	Char['5'] = {"eapmt374"};
	Char['6'] = {"jdbfz573ysp"};
	Char['7'] = {"aejr6"};
	Char['8'] = {"qsojdbfkquz573ys"};
	Char['9'] = {"tqkfbdj375z"};
	Char['A'] = {"4c8","vx"};
	Char['B'] = {"sojdapsy374p"};
	Char['C'] = {"jdbfz573"};
	Char['D'] = {"adj374a"};
	Char['E'] = {"ea48","pt"};
	Char['F'] = {"ea4","pt"};
	Char['G'] = {"jdbfz56ytr","y8"};
	Char['H'] = {"a4","e8","pt"};
	Char['I'] = {"ae","48","c6"};
	Char['J'] = {"de375z"};
	Char['K'] = {"a4","eq8","pq"};
	Char['L'] = {"a48"};
	Char['M'] = {"4are8"};
	Char['N'] = {"4a8e"};
	Char['O'] = {"fbdj375zf"};
	Char['P'] = {"4adjosp"};
	Char['Q'] = {"6yjdbfz56","w8"};
	Char['R'] = {"4adjosp","q8"};
	Char['S'] = {"jdbfkqsy375z"};
	Char['T'] = {"ae","c6"};
	Char['U'] = {"az573e"};
	Char['V'] = {"a6e"};
	Char['W'] = {"a5m7e"};
	Char['X'] = {"a8","4e"};
	Char['Y'] = {"6r","are"};
	Char['Z'] = {"ae48"};
	Char['a'] = {"y65zplnt8"};
	Char['b'] = {"a473tnk"};
	Char['c'] = {"tnlpz573"};
	Char['d'] = {"e85zplo"};
	Char['e'] = {"uxtnlpz58"};
	Char['f'] = {"edh;?","ko"};
	Char['g'] = {"85zplntBFD>","ot"};
	Char['h'] = {"a4","plms7"};
	Char['i'] = {"76rq","h"};
	Char['j'] = {"i","rs<@?9"};
	Char['k'] = {"a4","nu8"};
	Char['l'] = {"c67"};
	Char['m'] = {"4k","plr6","rnt8"};
	Char['n'] = {"4k","plms7"};
	Char['o'] = {"z573tnlpz"};
	Char['p'] = {"z573tnlp","kC"};
	Char['q'] = {"oG","tnlpz573"};
	Char['r'] = {"4k","plms"};
	Char['s'] = {"z573xvplnt"};
	Char['t'] = {"ko","c173"};
	Char['u'] = {"kz562","n78"};
	Char['v'] = {"k6o"};
	Char['w'] = {"kp5r7to"};
	Char['x'] = {"k8","o4"};
	Char['y'] = {"kz573","oBFD>"};
	Char['z'] = {"ko48"};
	Char['+'] = {"pt","h1"};
	Char['-'] = {"ps"};
	Char['*'] = {"f3","jz"};
	Char['/'] = {"e4"};
	Char['\\'] = {"a8"};
	Char[','] = {"y7"};
	Char['.'] = {"5"};
	Char['?'] = {"fbdjorw","6"};
	Char['!'] = {"cw","6"};
	Char[':'] = {"h","w"};
	Char['#'] = {"fj","uy","b5","d7"};
	Char['|'] = {"cm","r6"};
	Char['\''] = {"dm"};
	Char['\"'] = {"cl","en"};
	Char['~'] = {"plso"};
	Char['['] = {"ca46"};
	Char[']'] = {"ce86"};
	Char['<'] = {"jp3"};
	Char['>'] = {"ftz"};
	Char['%'] = {"abgfa","e4","23872"};
	Char['$'] = {"oigkqsy375z","c;"};
	Char['_'] = {"48"};
	Char['='] = {"ko","uy"};
	Char['{'] = {"dcglpv067"};
	Char['}'] = {"bcintx265"};
	Char['('] = {"dlv7"};
	Char[')'] = {"bnx5"};
	Char['^'] = {"lcn"};
	Char['@'] = {"smqwsxyjdbfz473"};
	Char[';'] = {"h","w15"};
	Char[4] = {"r"};
	Char[10] = {"pht","1h"};
	Char[11] = {"p1t","1h"};
	Char[12] = {"hp1","pt"};
	Char[13] = {"ht1","pt"};
	Char[14] = {"uz3y"};
	Char[15] = {"kco","0c","2c"};
	Char[16] = {"msw","ps","j3"};
	Char[17] = {"jyu","qu0"};
	Char[18] = {"ae","4m8","vx"};
	Char[19] = {"r","ht1ph","f","j","z","3"};
	Char[22] = {"jfz","l3","o0"};
	Char[23] = {"akoyw6"};
	Char[24] = {"gv","ix","p1t"};
	Char[25] = {"cpt6"};
	Char[26] = {"mz","m3","uz0","23y","g","i"};
	Char[27] = {"hm","nj","st","x3","w1","vz","qp","lf"};
	Char[28] = {"0uph","fhr","ioy6","w68"};
	Char[29] = {"z3","p0","t2","h1"};
	Char[30] = {"pt","f3","jz"};
}

bool IsHardOType(string Name) {
	if ((Name=="A")||(Name=="X")||(Name=="Z-1")||(Name=="O-3")
	||(Name=="O-6")||(Name=="O-7")||(Name=="RO-7")||(Name=="O-10")) return true;
	//if ((Name.empty())||(Name[0]!='?')) return false;
	return false; 
	//int n=Name.size(); if (n<3) return false;
	//return ((Name[n-2]=='-')&&(Name[n-1]=='1'));
}
bool IsBigOType(string Name) {
	if ((Name.size()>=2)&&((Name[0]=='O')&&(Name[1]==':'))) return true;
	return ((Name=="O-3")||(Name=="O-7")||(Name=="RO-7")||(Name=="O-10"));
}
bool IsHalfSame(string Name) {
	return ((Name=="S")||(Name=="Z")||(Name=="O")||(Name=="I")
	||(Name=="A")||(Name=="B")||(Name=="D")
	||(Name=="I5")||(Name=="S5")||(Name=="Z5")||(Name=="X")
	||(Name=="I6")||(Name=="O6")||(Name=="S6")||(Name=="Z6")
	||(Name=="s6")||(Name=="z6")||(Name=="LZ")||(Name=="LS")
	||(Name=="MW")||(Name=="WM"));
}
bool IsStrictHalfSame(string Name) {
	if ((Name.size()>=2)&&((Name[0]=='h')&&(Name[1]==':'))) return true;
	return ((Name=="D")||(Name=="I5")||(Name=="S5")||(Name=="Z5"));
}
bool IsOType(string Name) {
	if ((Name.size()>=2)&&(((Name[0]=='o')||(Name[0]=='O'))&&(Name[1]==':'))) return true;
	return ((Name=="O")||(IsHardOType(Name)));
}
bool IsEvenOType(string Name) {
	return ((Name=="O")||(Name=="A")||(Name=="Z-1")
	||(Name=="O-6")||(Name=="O-7")||(Name=="RO-7")||(Name=="O-10"));
}
bool IsCType(string Name) {
	return ((Name=="C")||(Name=="V")||(Name=="W")||(Name=="A6")||(Name=="E6")||(Name=="J-4"));
}
bool IsComplex(string Name) {
	return !((Name=="A")||(Name=="B")||(Name=="C")||
	(Name=="I")||(Name=="J")||(Name=="L")||(Name=="O")||(Name=="S")||(Name=="T")||(Name=="Z"));
}
pair<int,int> GetShift(int Dir, string Name, ERotateSystem Rule) {
	Dir = (Dir%4+4)&3;
	if (Rule==R_ASC) {
		if (IsEvenOType(Name)) return vector<pair<int,int> >({{0,0},{0,-1},{-1,-1},{-1,0}})[Dir];
		if (Name=="I") return vector<pair<int,int> >({{0,0},{0,+1},{+1,+1},{+1,0}})[Dir];
	}
	if (Rule==R_RNRS) {
		if ((Name=="I")||(Name=="B")||(Name=="I6")||(Name=="S")||(Name=="Z"))
			return vector<pair<int,int> >({{0,-1},{-1,0},{0,0},{0,0}})[Dir];
	}
	if (Rule==R_LNRS) {
		if ((Name=="I")||(Name=="B")||(Name=="I6")||(Name=="S")||(Name=="Z"))
			return vector<pair<int,int> >({{0,-1},{-1,0},{0,0},{0,0}})[Dir];
	}
	if ((Rule==R_ARS)||(Rule==R_Sega)) {
		if (Name=="I") return vector<pair<int,int> >({{0,0},{0,0},{0,+1},{+1,0}})[Dir];
		if ((Name=="J")||(Name=="L")||(Name=="S")||(Name=="T")||(Name=="Z")
		||(Name=="B")||(Name=="U")||(Name=="P")||(Name=="Q")) {
			if (!Dir) return {0,-1};
		}
		if ((Name=="L5")||(Name=="J5")||(Name=="Y")||(Name=="R")||(Name=="N")||(Name=="H")) {
			if (!(Dir&1)) return {0,-1};
		}
		if ((Name=="S")&&(Dir==1)) return {-1,0};
		if ((Name=="Z")&&(Dir==3)) return {+1,0};
	}
	if (Rule==R_New) {
		if (Name=="I")
			return vector<pair<int,int> >({{0,-1},{-1,0},{0,0},{0,0}})[Dir];
		if (Name=="J")
			return vector<pair<int,int> >({{0,0},{0,0},{0,+1},{+1,0}})[Dir];
		if (Name=="L")
			return vector<pair<int,int> >({{0,0},{-1,0},{0,+1},{0,0}})[Dir];
		if (Name=="S")
			return vector<pair<int,int> >({{0,0},{0,0},{0,+1},{+1,0}})[Dir];
		if (Name=="Z")
			return vector<pair<int,int> >({{0,0},{-1,0},{0,+1},{0,0}})[Dir];
	}
	if (Rule==R_Atari) {
		if (Name=="I")
			return vector<pair<int,int> >({{0,+1},{-1,0},{0,+2},{0,0}})[Dir];
		if (IsOType(Name)) return make_pair(0,0);
		return vector<pair<int,int> >({{0,0},{-1,0},{0,+1},{0,0}})[Dir];
	}
	if (Rule==R_Zhoumetry) {
		if (Name=="I") {
			if (Dir) return make_pair(0,-1);
		}
		if (!IsOType(Name)) {
			if (Dir==1) return make_pair(-1,0);
			if (Dir==2) return make_pair(0,+1);
		}
	}
	return make_pair(0,0);
}
int dx[4] = {1,0,-1,0};
int dy[4] = {0,-1,0,1};
pair<int,int> GetDXOffset(int Dir, string Name) {
	if (IsOType(Name)) return make_pair(0,0);
	return make_pair(dx[Dir],dy[Dir]);
}
vector<pair<int,int> > GetKick(int Dir, int Dest, string Name, ERotateSystem Rule) {
	if (Dir==Dest) Dest=((Dir+2)&3);
	if (Dir&1) Dir^=2;
	if (Dest&1) Dest^=2;
	if (Rule==R_SRSPlus) {
		if (Name=="I") return SRS_I[Dir][Dest];
		if (Name=="C") return SRS_C[Dir][Dest];
		if ((Name=="B")||(Name=="D")||(Name=="J")||(Name=="L")||(Name=="O")||(Name=="S")||(Name=="T")||(Name=="Z")) return SRS[Dir][Dest];
		//if (IsHardOType(Name)) return DefRot_O[Dir][Dest];
		if (((Dir+3)&3)==Dest) return ASCDX_CW;
		if (((Dir+1)&3)==Dest) return ASCDX_CCW;
		if (Dir<2) return ASCDX_FLIP;
		return ASCDX_RFLIP;
	}
	if (Rule==R_Default) {
		if (Name=="I") return DefRot_I[Dir][Dest];
		if (Name=="C") return DefRot_C[Dir][Dest];
		if (IsBigOType(Name)) return ASCDX_O[Dir][Dest];
		if (IsOType(Name)) return DefRot_O[Dir][Dest];
		if ((((Dir+2)&3)==Dest)&&(IsStrictHalfSame(Name))) return DefRot_O[Dir][Dest];
		if ((Name=="B")||(Name=="D")||(Name=="J")||(Name=="L")||(Name=="S")||(Name=="T")||(Name=="Z")) return DefRot[Dir][Dest];
		if (((Dir+3)&3)==Dest) return DefRot_CW;
		if (((Dir+1)&3)==Dest) return DefRot_CCW;
		if (Dir<2) return DefRot_FLIP;
		return DefRot_RFLIP;
	}
	if (Rule==R_ASCDX) {
		if (IsOType(Name)) return ASCDX_O[Dir][Dest];
		if ((((Dir+2)&3)==Dest)&&(IsStrictHalfSame(Name))) return ASCDX_O[Dir][Dest];
		if (((Dir+3)&3)==Dest) return ASCDX_CW;
		if (((Dir+1)&3)==Dest) return ASCDX_CCW;
		if (Dir<2) return ASCDX_FLIP;
		return ASCDX_RFLIP;
	}
	if (Rule==R_StrictSRSPlus) {
		if (Name=="I") return SRS_I[Dir][Dest];
		if (IsCType(Name)) return SRS_C[Dir][Dest];
		return SRS[Dir][Dest];
	}
	if (Rule==R_ASC) {
		if (((Dir+3)&3)==Dest) return ASC_CW;
		if (((Dir+1)&3)==Dest) return ASC_CCW;
		if (Dir<2) return ASC_CCW;
		return ASC_CW;
	}
	if (Rule==R_C2) return C2;
	if (Rule==R_DX) {
		pair<int,int> os=GetDXOffset(Dir,Name), ot=GetDXOffset(Dest,Name);
		return {{0,0},{os.second-ot.second,os.first-ot.first}};
	}
	if (Rule==R_ARS) {
		if (IsComplex(Name)) {
			if ((Dir&1)&&(!(Dest&1))) {
				if ((Name=="I5")||(Name=="J5")||(Name=="L5")||(Name=="Y")||(Name=="R"))
					return {{0,0},{+1,0},{-1,0},{0,-1},{0,+1},{2,0},{-2,0}};
			}
			return {{0,0},{+1,0},{-1,0},{0,-1}};
		}
		if ((((Dir&1)&&(!(Dest&1))))&&(Name=="I")) return {{0,0},{0,+1},{0,+2}};
		if ((((Dir&1)&&(!Dest)))&&(Name=="T")) return {{0,0},{+1,0},{-1,0},{0,+1}};
		if (Name!="I") return {{0,0},{+1,0},{-1,0}};
	}
	if (Rule==R_New) {
		if (((Dir+3)&3)==Dest) return {{0,0},{+1,0},{0,-1},{-1,0},{0,+1}};
		if (((Dir+1)&3)==Dest) return {{0,0},{-1,0},{0,-1},{+1,0},{0,+1}};
	}
	if (Rule==R_TetraX) {
		if (Name=="I") return TX_I[Dir][Dest];
		return TX[Dir][Dest];
	}
	if (Rule==R_Zhoumetry) {
		if ((((Dir+2)&3)==Dest)&&((Name=="J")||(Name=="L")))
			return {{0,0},{0,1},{0,-1},{1,0},{-1,0},{1,1},{-1,1},
			{0,2},{0,-2},{1,-1},{-1,-1},{2,0},{-2,0},
			{1,2},{-1,2},{2,1},{-2,1},{2,-1},{-2,-1}};
		return {{0,0},{0,-1},{0,-2},{1,-1},{-1,-1},{1,-2},{-1,-2},
		{0,1},{0,2},{1,0},{-1,0},{2,0},
		{-2,0},{1,1},{-1,1},{2,1},{-2,1},{2,-1},
		{-2,-1},{1,2},{-1,2},{2,2},{-2,2}};
	}
	return None;
}
vector<pair<int,int> > GetKickTable(int Dir, int Dest, string Name, ERotateSystem Rule) {
	if ((Name.size()>=2)&&(Name[Name.size()-2]=='@')) {
		int del = 0;
		if (Name.back()=='R') del=1;
		if (Name.back()=='D') del=2;
		if (Name.back()=='L') del=3;
		Dir = ((Dir+del)&3);
		Dest = ((Dest+del)&3);
		Name.pop_back(); Name.pop_back();
	}
	vector<pair<int,int> > res = GetKick(Dir,Dest,Name,Rule);
	pair<int,int> FromShift=GetShift(Dir,Name,Rule), ToShift=GetShift(Dest,Name,Rule);
	for (pair<int,int> &o : res) {
		o.first += ToShift.first-FromShift.first;
		o.second += ToShift.second-FromShift.second;
	}
	return res;
}
struct AccessMap {
	int LX, LY; bool **B[4];
	AccessMap(int _LX, int _LY) {
		LX=max(2,min(100,_LX)); LY=max(1,min(100,_LY));
		for (int d=0; d<4; ++d) {
			B[d] = new bool*[LX+2];
			for (int i=0; i<=LX+1; ++i) {
				B[d][i]=new bool[LY+2]; memset(B[d][i],0,LY+2);
			}
		}
	}
	bool Query(int d, int x, int y) {
		if ((d<0)||(d>3)) return false;
		if (((x<0)||(y<0))||((x>LX)||(y>LY))) return false;
		return B[d][x][y];
	}
	~AccessMap() {
		for (int d=0; d<4; ++d) {
			for (int i=0; i<=LX+1; ++i) delete[] B[d][i];
			delete[] B[d];
		}
	}
};
struct Instruction {
	int ord, d, x, y; bool sp;
	bool operator !=(Instruction _) const {
		return ((ord!=_.ord)||(d!=_.d)||(x!=_.x)||(y!=_.y));
	}
	bool operator ==(Instruction _) const {
		return ((ord==_.ord)&&(d==_.d)&&(x==_.x)&&(y==_.y));
	}
};
struct Status {
	int LX, LY;
	bool **B; Piece Cur; vector<Piece> Hold, Next;
	ll AccEval; Instruction Inst;
	int Combo, LineAfterPC; bool Clutch;
	pair<string,int> LastClearType;
	Status(int _LX, int _LY) {
		LX=max(2,min(100,_LX)); LY=max(1,min(100,_LY)); Inst=(Instruction){-1,0,0,0,false};
		B = new bool*[LX+2];
		for (int i=0; i<=LX+1; ++i) {
			B[i]=new bool[LY+2]; memset(B[i],0,LY+2);
		}
		Combo = 0;
	}
	Status(const Status &_From) {
		LX=_From.LX; LY=_From.LY;
		LineAfterPC = _From.LineAfterPC;
		LastClearType = _From.LastClearType;
		B = new bool*[LX+2];
		Hold=_From.Hold; Next=_From.Next;
		Inst=_From.Inst; AccEval=_From.AccEval;
		for (int i=0; i<=LX+1; ++i) {
			B[i]=new bool[LY+2]; memset(B[i],0,LY+2);
		}
		for (int i=1; i<=LX; ++i) {
			for (int j=1; j<=LY; ++j) B[i][j]=_From.B[i][j];
		}
		Combo = _From.Combo;
		Clutch = _From.Clutch;
	}
	void operator=(const Status &_From) {
		if ((LX!=_From.LX)||(LY!=_From.LY)) {
			if (B!=nullptr) {
				for (int i=0; i<=LX+1; ++i) {
					if (B[i]!=nullptr) delete[] B[i];
				}
				delete[] B; B=nullptr;
			}
		}
		LX=_From.LX; LY=_From.LY;
		LineAfterPC = _From.LineAfterPC;
		LastClearType = _From.LastClearType;
		if (B==nullptr) B=new bool*[LX+2];
		Hold=_From.Hold; Next=_From.Next;
		Inst=_From.Inst; AccEval=_From.AccEval;
		for (int i=0; i<=LX+1; ++i) {
			if (B[i]==nullptr) {
				B[i]=new bool[LY+2]; for (int j=0; j<=LY+1; ++j) B[i][j]=0;
			}
		}
		for (int i=1; i<=LX; ++i) {
			for (int j=1; j<=LY; ++j) B[i][j]=_From.B[i][j];
		}
		Combo = _From.Combo;
		Clutch = _From.Clutch;
	}
	bool CheckGrid(int x, int y) {
		if (((x<1)||(y<1))||((x>LX)||(y>LY))) return true;
		return B[x][y];
	}
	bool CheckPlace(Piece &p, int x, int y) {
		int LX = p.GetLX();
		for (int i=0; i<LX; ++i) {
			for (int j=0; j<LX; ++j) {
				if ((p.GetGrid(i,j))&&(CheckGrid(x+i,y+j))) return false;
			}
		}
		return true;
	}
	llu GetHash(int HoldLen) {
		llu res = 0LLU;
		vector<llu> PieceOpt; PieceOpt.push_back(Cur.GetHash());
		for (Piece p : Hold) PieceOpt.push_back(p.GetHash());
		int tot = 0;
		for (Piece p : Next) {
			if (PieceOpt.size()>=HoldLen+1) break;