为了证明窝最近没有颓废
(并且为了多骗点访问量
游戏链接:https://botzone.org/game/Tetris2
大概就是先写个估价,然后剪剪枝搜它4步。
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<cstring>
#define INF 1e180
using namespace std; #define MAPWIDTH 10
#define MAPHEIGHT 20 //W1 防长条
//W2、W3 优先放两边
//W4 forfuture
//W5、W6 封顶
//W7 多给长条
//W8 maxheiht
//W9、13 拒绝不可达行
//W10 高度系数
//W11 unreachable
//W12 奖励行
const int GO[][]={{,,,},{,,,},{,,,},{,,,},{,,,},{,,,},{,,,}};
const bool TYPEwork[]={,,,,,,};
const int M_DEEP=,E_DEEP=,RE=,intwo=;
double W1=1.2,W2=0.998,W3=0.98,W4=,W5=1.4,W6=,prize=,W7=,W8=,W9=,W10=,W11=,W12=intwo?:,W13=1.4,paper=;
int Work_num=,Type_num=;
#define CONDITION (x==5&&y==3&&o==1)||(x==1&&y==2&&o==1)
// 我所在队伍的颜色(0为红,1为蓝,仅表示队伍,不分先后)
int currBotColor;
int enemyColor; // 先y后x,记录地图状态,0为空,1为以前放置,2为刚刚放置,负数为越界
// (2用于在清行后将最后一步撤销再送给对方)
int gridInfo[][MAPHEIGHT + ][MAPWIDTH + ] = { }; // 代表分别向对方转移的行
int trans[][][MAPWIDTH + ] = { }; // 转移行数
int transCount[] = { }; // 运行eliminate后的当前高度
int maxHeight[] = { }; // 总消去行数的分数之和
int elimTotal[] = { }; // 连续几回合发生过消去了
int elimCombo[] = { }; // 一次性消去行数对应分数
const int elimBonus[] = { , , , , }; // 给对应玩家的各类块的数目总计
int typeCountForColor[][] = { };
int turnID, blockType;
int nextTypeForColor[];
double MMH=;
int debug;
#ifndef _BOTZONE_ONLINE
FILE *DEBUG=fopen("b.out","w");
#endif
bool forsize[MAPHEIGHT+][MAPWIDTH+][];
const int blockShape[][][] = {
{ { ,,,,-,,-,- },{ ,,,,,-,,- },{ ,,-,,,,, },{ ,,,-,,,-, } },
{ { ,,-,,,,,- },{ ,,,-,,,, },{ ,,,,-,,-, },{ ,,,,,-,-,- } },
{ { ,,,,,-,-,- },{ ,,,,,,,- },{ ,,-,,,,, },{ ,,,-,-,,-, } },
{ { ,,-,,,-,,- },{ ,,,-,,,, },{ ,,,,,,-, },{ ,,,,-,,-,- } },
{ { ,,-,,,,, },{ ,,,-,-,,, },{ ,,,,,-,-, },{ ,,,,,,,- } },
{ { ,,,-,,,, },{ ,,,,-,,-, },{ ,,,,,-,,- },{ ,,-,,,,, } },
{ { ,,,,-,,-, },{ ,,-,,,-,-,- },{ ,,,-,,-,,- },{ ,,,,,,, } }
}; // 7种形状(长L| 短L| 反z| 正z| T| 直一| 田格),4种朝向(上左下右),8:每相邻的两个分别为x,y const int rotateBlank[][][] = {
{ { ,,, },{ -,,, },{ -,-,, },{ ,-,, } },
{ { -,-,, },{ ,-,, },{ ,,, },{ -,,, } },
{ { ,,, },{ -,,, },{ -,-,, },{ ,-,, } },
{ { -,-,, },{ ,-,, },{ ,,, },{ -,,, } },
{ { -,-,-,,,,, },{ -,-,-,,,-,, },{ -,-,,,,-,, },{ -,,,,,-,, } },
{ { ,-,-,,-,,-,,-, } ,{ ,,-,-,-,-,-,-,-,- } ,{ -,,,-,,-,,-,,- } ,{ -,-,,,,,,,, } },
{ { , },{ , } ,{ , } ,{ , } }
}; // 旋转的时候需要为空的块相对于旋转中心的坐标 class Tetris
{
public:
const int blockType; // 标记方块类型的序号 0~6
int blockX; // 旋转中心的x轴坐标
int blockY; // 旋转中心的y轴坐标
int orientation; // 标记方块的朝向 0~3
const int(*shape)[]; // 当前类型方块的形状定义 int color; Tetris(int t, int color) : blockType(t), shape(blockShape[t]), color(color)
{ } inline Tetris &set(int x = -, int y = -, int o = -)
{
blockX = x == - ? blockX : x;
blockY = y == - ? blockY : y;
orientation = o == - ? orientation : o;
return *this;
} // 判断当前位置是否合法
inline bool isValid(int x = -, int y = -, int o = -)
{
x = x == - ? blockX : x;
y = y == - ? blockY : y;
o = o == - ? orientation : o;
if (o < || o > )
return false; int i, tmpX, tmpY;
for (i = ; i < ; i++)
{
tmpX = x + shape[o][ * i];
tmpY = y + shape[o][ * i + ];
if (tmpX < || tmpX > MAPWIDTH ||
tmpY < || tmpY > MAPHEIGHT ||
gridInfo[color][tmpY][tmpX] != )
return false;
}
return true;
} // 判断是否落地
inline bool onGround()
{
if (isValid() && !isValid(-, blockY - ))
return true;
return false;
} // 将方块放置在场地上
inline bool place()
{
if (!onGround())
return false; int i, tmpX, tmpY;
for (i = ; i < ; i++)
{
tmpX = blockX + shape[orientation][ * i];
tmpY = blockY + shape[orientation][ * i + ];
gridInfo[color][tmpY][tmpX] = ;
}
return true;
} // 检查能否逆时针旋转自己到o
inline bool rotation(int o)
{
if (o < || o > )
return false; if (orientation == o)
return true; int fromO = orientation;
int i, blankX, blankY;
while (true)
{
if (!isValid(-, -, fromO))
return false; if (fromO == o)
break; // 检查旋转碰撞
if (intwo) for (i = ; i < ; i++) {
blankX = blockX + rotateBlank[blockType][fromO][ * i];
blankY = blockY + rotateBlank[blockType][fromO][ * i + ];
if (blankX == blockX && blankY == blockY)
break;
if (gridInfo[color][blankY][blankX] != )
return false;
} fromO = (fromO + ) % ;
}
return true;
}
}; // 围一圈护城河
void init()
{
int i;
for (i = ; i < MAPHEIGHT + ; i++)
{
gridInfo[][i][] = gridInfo[][i][MAPWIDTH + ] = -;
gridInfo[][i][] = gridInfo[][i][MAPWIDTH + ] = -;
}
for (i = ; i < MAPWIDTH + ; i++)
{
gridInfo[][][i] = gridInfo[][MAPHEIGHT + ][i] = -;
gridInfo[][][i] = gridInfo[][MAPHEIGHT + ][i] = -;
}
} inline bool isValid(int map[MAPHEIGHT+][MAPWIDTH+],int type,int x,int y,int o){
if (o < || o > ) return false; int i, tmpX, tmpY;
for (i = ; i < ; i++){
tmpX = x + blockShape[type][o][ * i];
tmpY = y + blockShape[type][o][ * i + ];
if (tmpX < || tmpX > MAPWIDTH ||tmpY < || tmpY > MAPHEIGHT ||map[tmpY][tmpX] != )return false;
}
return true;
}
inline bool onGround(int map[MAPHEIGHT+][MAPWIDTH+],int type,int x,int y,int o){
if (isValid(map,type,x,y,o) && !isValid(map,type,x,y-,o))
return true;
return false;
}
inline bool rotation(int map[MAPHEIGHT+][MAPWIDTH+],int type,int x,int y,int o){
if (intwo) for (int i = ; i < ; i++) {
int blankX = x + rotateBlank[type][o][ * i];
int blankY = y + rotateBlank[type][o][ * i + ];
if (blankX == x && blankY == y) break;
if (map[blankY][blankX])
return ;
}
return ;
}
namespace Util
{ // 检查能否从场地顶端直接落到当前位置
inline bool checkDirectDropTo(int map[MAPHEIGHT+][MAPWIDTH+], int blockType, int x, int y, int o)
{
const int *def = blockShape[blockType][o];
for (; y <= MAPHEIGHT; y++)
for (int i = ; i < ; i++)
{
int _x = def[i * ] + x, _y = def[i * + ] + y;
if (_y > MAPHEIGHT)
continue;
if (_y < || _x < || _x > MAPWIDTH || map[_y][_x])
return false;
}
return true;
}
void dfs(int map[MAPHEIGHT+][MAPWIDTH+],bool bo[MAPHEIGHT+][MAPWIDTH+][],int type,int x,int y,int o){
//cout<<x<<y<<o<<endl;
if (!isValid(map,type,x,y,o)) return;
if (bo[y][x][o]) return;
//if (debug) fprintf(DEBUG,"O_O::::%d %d %d %d %d\n",x,y,o,bo[y][x][o],sizeof(bo));
bo[y][x][o]=;
dfs(map,bo,type,x-,y,o);dfs(map,bo,type,x+,y,o);dfs(map,bo,type,x,y-,o);
if (rotation(map,type,x,y,o))dfs(map,bo,type,x,y,(o+)%);
}
void init(int map[MAPHEIGHT+][MAPWIDTH+],bool bo[MAPHEIGHT+][MAPWIDTH+][],int type,bool de=){
debug=de;
memset(bo,,sizeof(forsize));
//if (debug) fprintf(DEBUG,"%d\n",type);
for (int o=;o<;o++)
for (int x=;x<=MAPWIDTH; x++){
if (checkDirectDropTo(map,type,x,MAPHEIGHT,o)) dfs(map,bo,type,x,MAPHEIGHT,o);
if (checkDirectDropTo(map,type,x,MAPHEIGHT-,o)) dfs(map,bo,type,x,MAPHEIGHT-,o);
if (type==) if (checkDirectDropTo(map,type,x,MAPHEIGHT-,o)) dfs(map,bo,type,x,MAPHEIGHT-,o);
} }
// 检查能否从场地顶端直接落到当前位置
inline bool checkDirectDropTo(int color, int blockType, int x, int y, int o)
{
auto &def = blockShape[blockType][o];
for (; y <= MAPHEIGHT; y++)
for (int i = ; i < ; i++)
{
int _x = def[i * ] + x, _y = def[i * + ] + y;
if (_y > MAPHEIGHT)
continue;
if (_y < || _x < || _x > MAPWIDTH || gridInfo[color][_y][_x])
return false;
}
return true;
} // 消去行
void eliminate(int color)
{
int &count = transCount[color] = ;
int i, j, emptyFlag, fullFlag, firstFull = , hasBonus = ;
maxHeight[color] = MAPHEIGHT;
for (i = ; i <= MAPHEIGHT; i++)
{
emptyFlag = ;
fullFlag = ;
for (j = ; j <= MAPWIDTH; j++)
{
if (gridInfo[color][i][j] == )
fullFlag = ;
else
emptyFlag = ;
}
if (fullFlag)
{
if (intwo&&firstFull && ++elimCombo[color] >= )
{
// 奖励行
for (j = ; j <= MAPWIDTH; j++)
trans[color][count][j] = gridInfo[color][i][j] == ? : ;
count++;
hasBonus = ;
}
firstFull = ;
for (j = ; j <= MAPWIDTH; j++)
{
// 注意这里只转移以前的块,不包括最后一次落下的块(“撤销最后一步”)
trans[color][count][j] = gridInfo[color][i][j] == ? : ;
gridInfo[color][i][j] = ;
}
count++;
}
else if (emptyFlag)
{
maxHeight[color] = i - ;
break;
}
else
for (j = ; j <= MAPWIDTH; j++)
{
gridInfo[color][i - count + hasBonus][j] =
gridInfo[color][i][j] > ? : gridInfo[color][i][j];
if (count)
gridInfo[color][i][j] = ;
}
}
if (count == )
elimCombo[color] = ;
maxHeight[color] -= count - hasBonus;
elimTotal[color] += elimBonus[count];
} // 转移双方消去的行,返回-1表示继续,否则返回输者
int transfer()
{
int color1 = , color2 = ;
if (transCount[color1] == && transCount[color2] == )
return -;
if (transCount[color1] == || transCount[color2] == )
{
if (transCount[color1] == && transCount[color2] > )
swap(color1, color2);
int h2;
maxHeight[color2] = h2 = maxHeight[color2] + transCount[color1];
if (h2 > MAPHEIGHT)
return color2;
int i, j; for (i = h2; i > transCount[color1]; i--)
for (j = ; j <= MAPWIDTH; j++)
gridInfo[color2][i][j] = gridInfo[color2][i - transCount[color1]][j]; for (i = transCount[color1]; i > ; i--)
for (j = ; j <= MAPWIDTH; j++)
gridInfo[color2][i][j] = trans[color1][i - ][j];
return -;
}
else
{
int h1, h2;
maxHeight[color1] = h1 = maxHeight[color1] + transCount[color2];//从color1处移动count1去color2
maxHeight[color2] = h2 = maxHeight[color2] + transCount[color1]; if (h1 > MAPHEIGHT) return color1;
if (h2 > MAPHEIGHT) return color2; int i, j;
for (i = h2; i > transCount[color1]; i--)
for (j = ; j <= MAPWIDTH; j++)
gridInfo[color2][i][j] = gridInfo[color2][i - transCount[color1]][j]; for (i = transCount[color1]; i > ; i--)
for (j = ; j <= MAPWIDTH; j++)
gridInfo[color2][i][j] = trans[color1][i - ][j]; for (i = h1; i > transCount[color2]; i--)
for (j = ; j <= MAPWIDTH; j++)
gridInfo[color1][i][j] = gridInfo[color1][i - transCount[color2]][j]; for (i = transCount[color2]; i > ; i--)
for (j = ; j <= MAPWIDTH; j++)
gridInfo[color1][i][j] = trans[color2][i - ][j]; return -;
}
} // 颜色方还能否继续游戏
inline bool canPut(int color, int blockType)
{
Tetris t(blockType, color);
for (int y = MAPHEIGHT; y >= ; y--)
for (int x = ; x <= MAPWIDTH; x++)
for (int o = ; o < ; o++)
{
t.set(x, y, o);
if (t.isValid() && checkDirectDropTo(color, blockType, x, y, o))
return true;
}
return false;
} // 打印场地用于调试
inline void printField()
{
#ifndef _BOTZONE_ONLINE
static const char *i2s[] = {
"~~",
"~~",
" ",
"[]",
"##"
};
cout << "~~:墙,[]:块,##:新块" << endl;
for (int y = MAPHEIGHT + ; y >= ; y--)
{
for (int x = ; x <= MAPWIDTH + ; x++)
cout << i2s[gridInfo[][y][x] + ];
for (int x = ; x <= MAPWIDTH + ; x++)
cout << i2s[gridInfo[][y][x] + ];
cout << endl;
}
#endif
}
}
int sum_n[]={,,,,,,,,,,,,,,,,,,,,};
double GetBoardTransitions(int map[MAPHEIGHT+][MAPWIDTH+]){
int mmh=; for (int _y=;_y<=MAPHEIGHT;_y++)
for (int _x=;_x<MAPWIDTH;_x++)
if ((map[_y][_x]&&!map[_y][_x+])||(!map[_y][_x]&&map[_y][_x+])) mmh++; for (int _y=;_y<MAPHEIGHT;_y++)
for (int _x=;_x<=MAPWIDTH;_x++)
if ((map[_y][_x]&&!map[_y+][_x])||(!map[_y][_x]&&map[_y+][_x])) mmh++; return mmh;
}
double GetBoardBuriedHoles(int map[MAPHEIGHT+][MAPWIDTH+]){
int mmh=; for (int _x=;_x<=MAPWIDTH;_x++){
int _y;
for (_y=MAPHEIGHT;_y;_y--) if (map[_y][_x]) break;
for (;_y;_y--) if (!map[_y][_x]) mmh++;
} return mmh;
}
double GetBoardWells(int map[MAPHEIGHT+][MAPWIDTH+]){
double mmh=,W; for (int _x=;_x<=MAPWIDTH;_x++){
int _y,wells=,f=;W=1.5;
for (_y=MAPHEIGHT;_y>=;_y--){
if(map[_y][_x]==){
if(map[_y][_x-]!=&&map[_y][_x+]!=) wells++;
}else{
mmh+=sum_n[wells]*W;
wells=;
if (f) W+=0.1;else W=0.8;
f=;
}
}
} return mmh;
}
int qx[],qy[],l,r;
const int f[][]={{,,,-},{,-,,}};
inline int bfs(int map[MAPHEIGHT+][MAPWIDTH+]){
l=r=;
bool bo[MAPHEIGHT+][MAPWIDTH+];
for (int _x=;_x<=MAPWIDTH;_x++)
for (int _y=;_y<=MAPHEIGHT;_y++) bo[_y][_x]=; for (int _x=;_x<=MAPWIDTH;_x++) if (!map[MAPHEIGHT][_x]) qx[r]=_x,qy[r]=MAPHEIGHT,r++;
while (l<r){
for (int i=;i<;i++)
if (!map[qy[l]+f[][i]][qx[l]+f[][i]]&&!bo[qy[l]+f[][i]][qx[l]+f[][i]])
bo[qy[l]+f[][i]][qx[l]+f[][i]]=,qy[r]=qy[l]+f[][i],qx[r]=qx[l]+f[][i],r++;
l++;
}
double mmh=;
for (int _x=;_x<=MAPWIDTH;_x++)
for (int _y=;_y<=MAPHEIGHT;_y++)
mmh+=(!map[_y][_x])&&(!bo[_y][_x]); return mmh;
}
int finalX, finalY, finalO,_finalX,_finalY,_finalO;
double work(int _map[MAPHEIGHT+][MAPWIDTH+],int ty,int deepth,double forfuture,bool currBotColor,int eRound);
bool canreach[][MAPHEIGHT+][MAPWIDTH+];
double Mavis(int _map[MAPHEIGHT+][MAPWIDTH+],int type,int x,int y,int o,int deepth,double MMH,bool currBotColor,int eRound){
bool _bo[MAPHEIGHT+][MAPWIDTH+][],cell_reach[MAPHEIGHT+][MAPWIDTH+];
int map[MAPHEIGHT+][MAPWIDTH+];
int emptynum[MAPHEIGHT+],sta[MAPHEIGHT+];
bool reach[MAPHEIGHT+];
double value[MAPHEIGHT+][MAPWIDTH+];
memset(emptynum,,sizeof(emptynum));
memset(sta,,sizeof(sta));
memset(reach,,sizeof(reach));
memset(cell_reach,,sizeof(cell_reach));
for (int _y=;_y<=MAPHEIGHT+;_y++)
for (int _x=;_x<=MAPWIDTH+;_x++) map[_y][_x]=_map[_y][_x];
double holenum=+prize*;
int ErodedPieceCellsMetric,erodedShape=; bool myCount[]={,,,,,,};
for (int i=;i<;i++){
myCount[i]=;
for (int j=;j<;j++)
if (i!=j&&typeCountForColor[currBotColor][i]+-typeCountForColor[currBotColor][j]>) myCount[i]=;
}
for (int i=;i<;i++){
int tmpX=x+blockShape[type][o][*i];
int tmpY=y+blockShape[type][o][*i+];
map[tmpY][tmpX]=;
} int pop=,O_O=;
for (int _y=;_y<=MAPHEIGHT;_y++){
int _x=;
for (_x=;_x<=MAPWIDTH;_x++)
if (!map[_y][_x]) break;
if (_x==MAPWIDTH+){
holenum-=prize;pop++;
for (_x=;_x<=MAPWIDTH;_x++) erodedShape+=map[_y][_x]==,map[_y][_x]=-;
}
}
ErodedPieceCellsMetric=pop*erodedShape;
for (int _x=;_x<=MAPWIDTH;_x++){
int p=;
for (int i=;i<=MAPHEIGHT;i++)
if (map[i][_x]!=-) map[p][_x]=map[i][_x],p++;
for (;p<=MAPHEIGHT;p++) map[p][_x]=;
} double P_P=;
int max=;
for (int _x=;_x<=MAPWIDTH;_x++){
int _y=MAPHEIGHT;
for (;_y;_y--) if (map[_y][_x]) break;
double cost=_y*_y;
int u=x<?x:x-;
cost*=pow(1.05,u);
P_P+=cost;
if (max<_y) max=_y;
}
int BoardTransitions=GetBoardTransitions(map),BuriedHoles=GetBoardBuriedHoles(map),Wells=GetBoardWells(map),Bfs=bfs(map); holenum=sqrt(P_P)/+2.5*max+*BoardTransitions+*BuriedHoles+*Bfs+Wells; if (pop&&eRound>) holenum-=W12; #ifndef _BOTZONE_ONLINE
if (CONDITION) fprintf(DEBUG,">_<%d %d %d %d\n",x,y,o,deepth);
if (CONDITION){
for (int y=MAPHEIGHT;y;y--,fprintf(DEBUG,"\n"))
for (int x=;x<=MAPWIDTH;x++)
fprintf(DEBUG,"%c",map[y][x]?'#':'.');
fprintf(DEBUG,"%d %d %d %d %d %lf\n",x,y,o,deepth,type,holenum);
fprintf(DEBUG,"ErodedPieceCellsMetric:%d\n",ErodedPieceCellsMetric);
fprintf(DEBUG,"BoardTransitions:%d\n",BoardTransitions);
fprintf(DEBUG,"BuriedHoles:%d\n",BuriedHoles);
fprintf(DEBUG,"Wells:%d\n\n",Wells);
}
#endif
//printf("%d %d %d %d\n",x,y,o,deepth);
if (deepth){
if (deepth==){
double forfuture=-INF,test;
for (int i=;i<;i++)
if (myCount[i]){
typeCountForColor[currBotColor][i]++;
if ((test=work(map,i,deepth-,forfuture,currBotColor,pop?eRound+:))>forfuture) forfuture=test;
typeCountForColor[currBotColor][i]--;
}
if (forfuture>=INF-) return INF-;
holenum+=forfuture*W4;
//printf("%d %d %d %lf %lf\n",x,y,o,holenum,forfuture);
}else{
int type_num=Type_num;
int TY[type_num];
double Work[type_num];
double forfuture=-INF,test;
for (int j=;j<type_num;j++) Work[j]=-INF;
for (int i=,j;i<;i++)
if (myCount[i]){
typeCountForColor[currBotColor][i]++; test=work(map,i,,forfuture,currBotColor,pop?eRound+:);
for (j=;j<type_num;j++) if (Work[j]<test) break;
if (j<type_num){
for (int k=type_num-;k>j;k--) TY[k]=TY[k-],Work[k]=Work[k-];
Work[j]=test;TY[j]=i;
} typeCountForColor[currBotColor][i]--;
} for (int i=;i<type_num;i++)
if (Work[i]>-INF+){
if (Work[]<){
if (Work[i]<Work[]*1.05-) break;
}else if (Work[i]<Work[]*0.95-) break;
typeCountForColor[currBotColor][TY[i]]++;
if ((test=work(map,TY[i],deepth-,forfuture,currBotColor,pop?eRound+:))>forfuture) forfuture=test;
typeCountForColor[currBotColor][TY[i]]--;
}
/*printf("%d\n",type_num);
for (int i=0;i<type_num;i++) printf("%lf ",Work[i]);puts("");
*/
if (forfuture>=INF-) return INF-;
holenum+=forfuture*W4;
//printf("%d %d %d %lf %lf\n",x,y,o,holenum,forfuture);
}
}
holenum-=ErodedPieceCellsMetric; return holenum;
}
double work(int _map[MAPHEIGHT+][MAPWIDTH+],int ty,int deepth,double forfuture,bool currBotColor,int eRound){
bool bo[MAPHEIGHT+][MAPWIDTH+][];
int fx=-,fy,fo,i,work_num=Work_num;
/*fprintf(DEBUG,">_<%d\n",ty);
for (int y=MAPHEIGHT;y;y--,fprintf(DEBUG,"\n"))
for (int x=1;x<=MAPWIDTH;x++)
fprintf(DEBUG,"%c",_map[y][x]?'#':'.');*/
double MMH=INF,test;
Util::init(_map,bo,ty);
if (deepth){
double work[work_num];
int XX[work_num],YY[work_num],OO[work_num];
for (i=;i<work_num;i++) work[i]=INF;
for (int y = ; y <= MAPHEIGHT; y++)
for (int x = ; x <= MAPWIDTH; x++)
for (int o = ; o < ; o++)
if (GO[ty][o]&&onGround(_map,ty,x,y,o)&&bo[y][x][o]){
test=Mavis(_map,ty,x,y,o,,MMH,currBotColor,eRound);
for (i=;i<work_num;i++) if (test<work[i]) break;
if (i==work_num) continue;
for (int j=work_num-;j>i;j--) work[j]=work[j-],XX[j]=XX[j-],YY[j]=YY[j-],OO[j]=OO[j-];
work[i]=test;XX[i]=x;YY[i]=y;OO[i]=o;
}
for (int i=;i<work_num;i++)
if (work[i]<INF-){
if (work[]<){
if (work[i]>work[]*0.8+) break;
}else if (work[i]>work[]*1.2+) break;
if ((test=Mavis(_map,ty,XX[i],YY[i],OO[i],deepth,MMH,currBotColor,eRound))<MMH){
fx=XX[i];fy=YY[i];fo=OO[i];
MMH=test;
if (MMH<forfuture) return MMH;
}
}
if (fx==-) fx=XX[],fy=YY[],fo=OO[];
}else{
for (int y = ; y <= MAPHEIGHT; y++)
for (int x = ; x <= MAPWIDTH; x++)
for (int o = ; o < ; o++)
if (GO[ty][o]&&onGround(_map,ty,x,y,o)&&bo[y][x][o]&&(test=Mavis(_map,ty,x,y,o,,INF,currBotColor,eRound))<MMH){
fx=x;
fy=y;
fo=o;
MMH=test;
if (MMH<forfuture) return MMH;
}
}
finalX=fx;finalY=fy;finalO=fo;
//printf("%d %d %d %d %d\n",ty,deepth,fx,fy,fo);
//fprintf(DEBUG,"===================================%d %d %d %d %lf\n",ty,finalX,finalY,finalO,MMH);
return MMH;
}
double gain(int _map[MAPHEIGHT+][MAPWIDTH+],int x,int y,int o,int ty,int _ty,bool currBotColor,int DEEPTH){
int map[MAPHEIGHT+][MAPWIDTH+];
for (int _y=;_y<=MAPHEIGHT+;_y++)
for (int _x=;_x<=MAPWIDTH+;_x++) map[_y][_x]=_map[_y][_x];
for (int i=;i<;i++){
int tmpX=x+blockShape[ty][o][*i];
int tmpY=y+blockShape[ty][o][*i+];
map[tmpY][tmpX]=;
} int pop=;
for (int _y=;_y<=MAPHEIGHT;_y++){
int _x=;
for (_x=;_x<=MAPWIDTH;_x++)
if (!map[_y][_x]) break;
if (_x==MAPWIDTH+){
pop++;
for (_x=;_x<=MAPWIDTH;_x++) map[_y][_x]=-;
}
}
for (int _x=;_x<=MAPWIDTH;_x++){
int p=;
for (int i=;i<=MAPHEIGHT;i++)
if (map[i][_x]!=-) map[p][_x]=map[i][_x],p++;
for (;p<=MAPHEIGHT;p++) map[p][_x]=;
} return work(map,_ty,DEEPTH,INF,currBotColor,pop?elimCombo[currBotColor]+:);
}
int blockForEnemy(int _map[MAPHEIGHT+][MAPWIDTH+],int ty,int DEEPTH){
int minCount = ,mmh=-;
for (int i = ; i < ; i++)
if (typeCountForColor[enemyColor][i] < minCount) minCount = typeCountForColor[enemyColor][i]; bool bo[MAPHEIGHT+][MAPWIDTH+][];
int fx=-,fy,fo,i,work_num=Work_num;
double MMH=INF,test;
Util::init(_map,bo,ty);
double work[work_num];
int XX[work_num],YY[work_num],OO[work_num];
for (i=;i<work_num;i++) work[i]=INF;
for (int y = ; y <= MAPHEIGHT; y++)
for (int x = ; x <= MAPWIDTH; x++)
for (int o = ; o < ; o++)
if (onGround(_map,ty,x,y,o)&&bo[y][x][o]){
test=Mavis(_map,ty,x,y,o,,MMH,currBotColor,elimCombo[currBotColor]);
for (i=;i<work_num;i++) if (test<work[i]) break;
if (i==work_num) continue;
for (int j=work_num-;j>i;j--) work[j]=work[j-],XX[j]=XX[j-],YY[j]=YY[j-],OO[j]=OO[j-];
work[i]=test;XX[i]=x;YY[i]=y;OO[i]=o;
} double _mmh=-INF;
for (int _ty=;_ty<;_ty++)
if (typeCountForColor[enemyColor][_ty]+-minCount<=){
typeCountForColor[enemyColor][_ty]++;
double _MMH=INF;
for (int i=;i<work_num;i++)
if (work[i]<INF-){
if (work[]<){
if (work[i]>work[]*0.8+) break;
}else if (work[i]>work[]*1.2+) break;
if ((test=gain(_map,XX[i],YY[i],OO[i],ty,_ty,enemyColor,DEEPTH))<_MMH){
_MMH=test;
//printf("===%d %lf\n",i,test);
}
} if (_MMH>_mmh) _mmh=_MMH,mmh=_ty; //printf("%d %lf\n",_ty,_MMH);
typeCountForColor[enemyColor][_ty]--;
}
return mmh;
}
int main(){
#ifndef _BOTZONE_ONLINE
freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
#endif
// 加速输入
istream::sync_with_stdio(false);
srand(time(NULL));
init(); cin >> turnID; // 先读入第一回合,得到自己的颜色
// 双方的第一块肯定是一样的
cin >> blockType >> currBotColor;
enemyColor = - currBotColor;
nextTypeForColor[] = blockType;
nextTypeForColor[] = blockType;
typeCountForColor[][blockType]++;
typeCountForColor[][blockType]++; // 然后分析以前每回合的输入输出,并恢复状态
// 循环中,color 表示当前这一行是 color 的行为
// 平台保证所有输入都是合法输入
for (int i = ; i < turnID; i++){
int currTypeForColor[] = { nextTypeForColor[], nextTypeForColor[] };
int x, y, o;
// 根据这些输入输出逐渐恢复状态到当前回合 // 先读自己的输出,也就是自己的行为
// 自己的输出是自己的最后一步
// 然后模拟最后一步放置块
cin >> blockType >> x >> y >> o; // 我当时把上一块落到了 x y o!
Tetris myBlock(currTypeForColor[currBotColor], currBotColor);
myBlock.set(x, y, o).place(); // 我给对方什么块来着?
typeCountForColor[enemyColor][blockType]++;
nextTypeForColor[enemyColor] = blockType; // 然后读自己的输入,也就是对方的行为
// 裁判给自己的输入是对方的最后一步
cin >> blockType >> x >> y >> o; // 对方当时把上一块落到了 x y o!
Tetris enemyBlock(currTypeForColor[enemyColor], enemyColor);
enemyBlock.set(x, y, o).place(); // 对方给我什么块来着?
typeCountForColor[currBotColor][blockType]++;
nextTypeForColor[currBotColor] = blockType; // 检查消去
Util::eliminate();
Util::eliminate(); // 进行转移
Util::transfer();
} // 做出决策(你只需修改以下部分)
// 遇事不决先输出(平台上编译不会输出)
work(gridInfo[currBotColor],blockType,M_DEEP,-INF,currBotColor,elimCombo[currBotColor]);
_finalX=finalX;_finalY=finalY;_finalO=finalO; int currTypeForColor[] = { nextTypeForColor[], nextTypeForColor[] };
Tetris myBlock(currTypeForColor[currBotColor], currBotColor);
myBlock.set(_finalX,_finalY,_finalO).place();
#ifndef _BOTZONE_ONLINE
Util::printField();
#endif
/*work(gridInfo[enemyColor],nextTypeForColor[enemyColor],1,-INF); Tetris enemyBlock(currTypeForColor[enemyColor], enemyColor);
enemyBlock.set(finalX,finalY,finalO).place();
//Util::printField(); Util::eliminate(0);
Util::eliminate(1);
Util::transfer();
*/
cout << blockForEnemy(gridInfo[enemyColor],nextTypeForColor[enemyColor],E_DEEP)<< " " << _finalX << " " << _finalY << " " << _finalO<<endl;
}