#define _USE_MATH_DEFINES
#include "consts.h"
#include <math.h>
#include <algorithm>
#include <vector>
#include <winsock2.h>
using namespace std;

inline int round(const float a) { return (int)(a + .5f); }
inline int astsin(const float w) {return round(127*sin(w));}
inline int astcos(const float w) {return round(127*cos(w));}
inline unsigned char dir_dist(const char a, const char b) {return abs( (a-b) );}
inline char dir_dist2(const char a, const char b) {return (a-b);}


template <class T,class C>
struct TVector {
	T x,y;
	TVector():x(0),y(0) {}
	TVector(const T x, const T y):x(x),y(y) {}

	bool operator==(const TVector &v) const {return (v.x==x&&v.y==y);}
	TVector operator-(const TVector &v) const {	return TVector(x-v.x,y-v.y); }
	TVector operator+(const TVector &v) const {	return TVector(x+v.x,y+v.y); }
	TVector operator*(const int &d) const	{	return TVector(x*d,y*d); }
	TVector operator*(const float &d) const	{	return TVector(x*d,y*d); }
	TVector operator/(const int &d) const	{	return TVector(x/d,y/d); }
	TVector operator/(const float &d) const	{	return TVector(x/d,y/d); }
	void operator=(const TVector &v) {
		x=v.x;
		y=v.y;}
 
	operator TVector<C,T>() const {
		return TVector<C,T>((C)x,(C)y);
	}

	double dist() const {return sqrt((double)(x*x+y*y));}
	T dist2() const {return x*x+y*y;}
	float dir() const {float ret=asinf(y/dist()); if(x<0) ret=M_PI-ret; if(ret<0) ret+=2*M_PI; return ret;}
};

typedef TVector<int,float> Vector;
typedef TVector<float,int> FVector;

struct Object;

#define MAX_COVER 4
#define NUM_CIRCLE 256
#define GESCHW_SCHUSS	8.f
#define GESCHW_DREHUNG	1.f//0.75f
#define BACKWARDS 8
#define LIFETIME 72

struct State {
	Object *obj;
	float t_warte,t_around,t_s;
	unsigned char pos;

	float get_min() const {return t_warte-t_around;}
	float get_max() const {return t_warte+t_around;}
};

struct Object {
	Vector pos;
	FVector force;
	int r,level;
	int value,svalue,num;
	int shot_time;
	bool bActive;
	Vector fs[8];
	float length,s_min;
	State *states[NUM_CIRCLE*MAX_COVER];
	bool bMultiply;

	float dbg_warte,dbg_s,dbg_around;

	Object(const Vector &p, const int r, const int v):bActive(false),length(0.f),pos(p),r(r),svalue(v),value(v),shot_time(-1),num(0),bMultiply(false),level(2) {}
	
	bool collidate(const FVector &Ray, float &t1, float &t2, const int r);
	bool collidate(const FVector &Ray, float &t1, float &t2);
	bool collidate(const Object &Obj, float &t1, float &t2);
	bool collidate(const FVector &Ray, const float l, State &state);

	virtual void clear() {
		level=2;
		s_min=100000;
		for(int i=0; i<NUM_CIRCLE*MAX_COVER; i++)
			states[i]=NULL;
	}

	Vector getPos(const int t) {
		if(num<1)
			return (Vector)(force*t)+pos;
		Vector ret=pos;
		for(int i=0; i<t; i++)
			ret=ret+fs[(num+1+i)%min(num,8)];
		return ret;
	}
	FVector getPos(const float t) {return (force*t)+(FVector)pos;}

	void normalize() {
		while (pos.x < -512) pos.x += 1024; // dx normalisieren auf -512 ... 511
		while (pos.x > 511) pos.x -= 1024;
		while (pos.y < -384) pos.y += 768;  // dy normalisieren auf -384 ... 383
		while (pos.y > 383) pos.y -= 768;
	}

	virtual float probability(State &st) {return 0.f;}
	virtual float probability() const {return 0.f;}
	virtual void setShot(const float t) {shot_time=t;}

	bool Set(const Vector &p) {
		--shot_time;
		if((p-pos).dist2()*GL_mul<=14*14) {
			fs[num%8]=(p-pos)*GL_mul;
			++num;
			force=fs[0];
			for(int i=1; i<8&&i<num; i++)
				force=force+fs[i];
			if(num>=8)
				force=force/8;
			else
				force=force/num;
			length=force.dist();

		}

		pos=p;
		bActive=true;
		return true;
	}

};

#define SMALL	14
#define MEDIUM	15
#define BIG		0

#define MUL		0.3f
struct Asteroid : public Object {
	int type,shape;
	float shots[2];
	float prop;

	Asteroid(const Vector &p, const int t, const int s):Object(p,0,0),type(t),shape(s) {
		shots[0]=shots[1]=-1.f;
		prop=0.f;
		switch(s) {
			case SMALL: r=8; value=10; break;
			case MEDIUM: r=16; value=5; bMultiply=true; break;
			case BIG: r=32; value=2; bMultiply=true; break;
		}
		pos=pos;
		svalue=value;
		bActive=true;
	}

	virtual void clear() {
		Object::clear();
		--shots[0];
		--shots[1];
		prop=0.f;
	}
	
	virtual float probability(State &st) {
		float prop;
		if(shot_time<0.f) {
			prop=1.f;
			if(st.t_s+st.t_warte>40)
				prop = min(4,num)/4.f;
			if(st.t_s<30&&st.t_warte>30&&shape!=SMALL)
				prop*=0.1;
			this->prop=max(this->prop,prop);
			return prop;
		}
		if(shape==SMALL) {
			return 0.f;
		}
		float avg=shot_time;
		if(shots[0]>=0.f) {
			avg+=shots[0];
			if(shots[1]>=0.f) {
				return 0.f;
			}
			avg*=0.5f;
		}

		prop=33.f/(st.t_s+0.1f);
		this->prop=max(this->prop,prop);

		return prop;
	}

	virtual float probability() const {
		return prop-0.1f;
	}

	virtual void setShot(const float t) {
		if(shape==SMALL) Object::setShot(t);
		else {
			if(shot_time<0) shot_time=t;
			else if(shots[0]<0) shots[0]=t;
			else shots[1]=t;
		}
	}

};

struct Saucer : public Object {
	int size;

	Saucer(const Vector &p, const int s):Object(p,0,20),size(s) {
		switch(s) {
			case SMALL: r=10; value=100; break;
			case MEDIUM: r=20; value=20;break;
		}

		bActive=true;
	}
	
	virtual float probability(State &st)  {
		if(shot_time>=0) return 0.f;
		return 1.0f;
	}
	
	virtual float probability() const {
		if(shot_time>=0) return 0.f;
		return 1.f;
	}
};

struct Shot : public Object {

	Shot(const Vector &p=Vector()):Object(p,2,0) {
		bActive=true;
	}

};

struct Segment {
	int num,value,objs;
	float col[2];
	float deg,x,y;
	Vector force,start;

	void clear() {
		objs=num=value=0;
		col[0]=col[1]=0.f;
	}

	Segment(){clear();}

	void setDeg(const float f) {
		deg=f;
		x=cosf(f);
		y=sinf(f);

		start.x = round( (floor(astcos(f)/2.f) + floor(floor(astcos(f)/4.f)))/8.f );
		start.y = round( (floor(astsin(f)/2.f) + floor(floor(astsin(f)/4.f)))/8.f );

		force.x = (floor(astcos(f)/2.f));
		force.y = (floor(astsin(f)/2.f));
	}
};

struct Ship : public Object {
	Vector vDir;
	bool ship_present;
	int dir,olddir[BACKWARDS];

	Ship():Object(Vector(0,0),30,0),ship_present(false),dir(0) {
		for(int i=0; i<BACKWARDS; i++) olddir[i]=0;}

	void setDir(const Vector &v) {
		vDir=v;
		int n=4;
		if(v==Vector(0,1536)||v==Vector(0,-1536))
			n=1;
		else if(v==Vector(1536,0)||v==Vector(-1536,0))
			n=7;

		for(int i=0; i<64; i++) {
			if(GL_dirs[i][0]==v.x&&GL_dirs[i][1]==v.y) {
				int min=0;
				for(int j=1; j<n; j++) {
					if(dir_dist(GL_dirs[i][j+2],dir)<dir_dist(GL_dirs[i][min+2],dir))
						min=j;
				}
				dir=GL_dirs[i][min+2];
				break;
			}
		}

		while(dir<0) dir+=NUM_CIRCLE;
		dir%=NUM_CIRCLE;
	}

	FVector getShotForce(const Segment &seg) const {
		FVector ft=seg.force;
		ft=ft+force*8;
		if(ft.x<-111)
			ft.x=-111;
		else if(ft.x>111)
			ft.x=111;
		if(ft.y<-111)
			ft.y=-111;
		else if(ft.y>111)
			ft.y=111;
		ft=ft/8;
		return ft;
	}

	void setDir(const int d) {
		dir+=d;
		while(dir<0) dir+=NUM_CIRCLE;
		dir%=NUM_CIRCLE;
		for(int i=0; i<BACKWARDS-1; i++)
			olddir[i]=olddir[i+1];
		olddir[BACKWARDS-1]=d;
	}

	void set(int x, int y, int rx, int ry,bool b)
	{
		Vector p(x,y);		
		if((p-pos).dist2()<14*14)
			force=((FVector)p-(FVector)pos);
		pos=Vector(x,y);
		setDir(Vector(rx,ry));
		ship_present=b;
	}
};

struct Slot {
	unsigned char num;
	State *states;
	float min;
	
	Slot() {states=new State[27*MAX_COVER];num=0;min=-1000;}
	~Slot(){delete [] states;}
	
	void clear() {num=0;--min; if(min<0) min=-1000;}
	void set(unsigned char c) {for(int i=0; i<27*MAX_COVER; i++) states[i].pos=c;}
};

struct Circle {
	Segment segs[NUM_CIRCLE];
	Slot slots[NUM_CIRCLE];
	float next_shots[4];
	
	float avg(const int dir, const Object *obj) {
		float avg=0;
		int n=0;
		int i=0;
		while(obj->states[i]) {
			if((dir_dist(obj->states[i]->pos,dir)+obj->states[i]->get_min())>=0 ) {
				avg+=obj->states[i]->get_min()+obj->states[i]->t_s;
				++n;
			}
			++i;
		}				
		if(n==0)
			return 100000000;
		return avg/n;
	}

	Circle() {		
		for(int i=0; i<4; i++)
			next_shots[i]=-1;
		for(int i=0; i<NUM_CIRCLE; i++) {
			segs[i].setDeg(GL_degs[i]*M_PI/180.f);
			slots[i].set((unsigned char)i);
		}
	}

	void clear(Object **objs, const int num) {
		for(int i=0; i<4; i++)
			next_shots[i]-=1.f;
		for(int i=0; i<NUM_CIRCLE; i++) {
			segs[i].clear();
			slots[i].clear();
		}
		for(int j=0; j<num; j++)
			objs[j]->clear();
	}

	int tree2(const int gone, Object **objs, const int num, bool *bObj,float *shots, const int dir, int *pos, const int tiefe) const {
		if(tiefe<0) return gone*2;
		int time=1000000000;
		static float copy[4];
		int resa=-1,resb=-1;
		int n=0;

		for(int i=0; i<num; i++) {
			if(bObj[i]) {
				++n;
				continue;
			}

			int b=0;
			int min=-1;
			while(objs[i]->states[b]) {
				if( (min==-1||objs[i]->states[b]->t_warte<objs[i]->states[min]->t_warte)&&objs[i]->states[b]->t_warte>gone+1&&objs[i]->states[b]->t_warte>=shots[0]&&objs[i]->states[b]->t_warte>=dir_dist(dir,objs[i]->states[b]->pos)&&(num<6||objs[i]->states[b]->t_warte-gone<128)) {
					min=b;
				}
				++b;
				if(b>=NUM_CIRCLE*MAX_COVER) break;
			}

			if(min<0||gone+objs[i]->states[min]->t_warte>*(pos+2))
				continue;
			
			bObj[i]=true;
			bool bFound=true;
			for(int k=0; k<num&&bFound; k++) {
				if(bObj[i]) continue;
				b=0;
				bFound=false;
				while(objs[k]->states[b]) {
					if(objs[i]->states[b]->t_warte>gone+1+objs[i]->states[min]->t_warte) {
						bFound=true;
						break;
					}
					++b;
					if(b>=NUM_CIRCLE*MAX_COVER) break;
				}
			}
			if(bFound) {
			memcpy(copy,shots,sizeof(float)*4);
			for(int l=0; l<4; l++)
				shots[l]-=objs[i]->states[min]->t_warte;
			set_Shots(shots,objs[i]->states[min]->t_s);
			int temp=tree2(gone+objs[i]->states[min]->t_warte,objs,num,bObj,shots,objs[i]->states[min]->pos,pos,tiefe-1)+objs[i]->states[min]->t_warte;
			if(temp<time) {
				time=temp;
				resa=i;
				resb=min;
			}
			memcpy(shots,copy,sizeof(float)*4);
			}
			bObj[i]=false;
		}

		*pos=resa;
		*(pos+1)=resb;


		if(num-n<=*(pos+3)) {
			if(gone<*(pos+2)) {
				*(pos+2)=gone;
				*(pos+3)=num-n;
			}
			if(num==n) return 0;
		}

		if(resa==-1)
			return 1000000000;

		return time;
	}

	float min_from_object(Object *obj) const {
		int b=0;
		int min=-1;
		while(obj->states[b]) {
			if( (min==-1||obj->states[b]->t_warte<obj->states[min]->t_warte)&&obj->states[b]->t_warte>=obj->states[b]->t_around) {
				min=b;
			}
			++b;
			if(b>=NUM_CIRCLE*MAX_COVER) break;
		}
		if(min==-1||obj->states[min]->t_warte<obj->states[min]->t_around) return 100000000.f;
		return obj->states[min]->t_warte;
	}

	void tree1(Object **objs, const int num, int &sl, int &st, const int dir, const int max_level) const {
		bool bObj[27];
		float min[27],min2[27];
		int nn=0;
		for(int i=0; i<num; i++) {
			bObj[i] = objs[i]->level!=max_level||objs[i]->probability()<0.5f;
			if(!bObj[i]) {
				min[i]=min_from_object(objs[i])/(objs[i]->level*objs[i]->level);
				++nn;
			}
		}
		if(nn<1) {
			nn=0;
			for(int i=0; i<num; i++) {
				bObj[i] = objs[i]->probability()<0.5f;
				if(!bObj[i]) { 
					++nn;
				}
			}
		}

		if(nn>5) {
		memcpy(min2,min,sizeof(float)*num);
		sort(min,min+num);
		int m=min[4];
		if(nn>11)
			m=min[5];
		for(int i=0; i<num; i++) {
			if(bObj[i]) continue;
			bObj[i] = min2[i]>m;
		}
		}

		float shots[4];

		for(int i=0; i<4; i++) shots[i]=next_shots[i];

		static int cont[4]={-1,-1,500};
		//cont[0]=cont[1]=-1;
		cont[2]=700;
		cont[3]=num+1;
		int ret=tree2(0,objs,num,bObj,shots,dir,cont,8);

		if(cont[0]!=-1) {
			sl=objs[cont[0]]->states[cont[1]]->pos;
			for(int i=0; i<slots[sl].num; i++)
				if(&slots[sl].states[i]==objs[cont[0]]->states[cont[1]]) {
					st=i;
					break;
				}
		}
	}

	static void set_Shots(float *shots, float ts) {
			char sch=0;
			for(int i=0; i<4; i++)
				if(shots[i]<0) {sch++;break;}
			if(sch>0) {
				shots[0]=shots[1];
				shots[1]=shots[2];
				shots[2]=shots[3];
				shots[3]=-1;
			}
			bool b=false;
			for(int i=0; i<4; i++) {
				if(ts<shots[i]) {
					for(int j=3; j>i; j--)
						shots[j]=shots[j-1];
					shots[i]=ts;
					b=true;
					break;
				}
			}
			if(!b)
				shots[3]=ts;
	}

	int calc2(Object **objs, const int num, const Ship &sh, const bool &bF, const int frame_number, int &dur, int &dur2, const bool kann) {
		
		//build up data
		for(int i=0; i<NUM_CIRCLE; i++) {
			if(kann) 
				i=sh.dir;
			float length=sh.getShotForce(segs[i]).dist();
			for(int j=0; j<num; j++) {
				if(((objs[j]->shot_time>=0&&!objs[j]->bMultiply)||(objs[j]->bMultiply&&num>24))||objs[j]->value<1) continue;

				float time=0.f;
				Object cp=*objs[j];
				cp.pos=cp.pos+cp.force-segs[i].start;

				for(int n1=0, n2=0; n1<MAX_COVER&&n2<6; n2++) {

					cp.normalize();

					int alt=slots[i].num;

					if(cp.collidate(sh.getShotForce(segs[i]),length,slots[i].states[slots[i].num])) {
						slots[i].states[slots[i].num].t_warte+=time;
						//TODO: check because of next available shot
						if(slots[i].states[slots[i].num].t_warte>slots[i].min-5.3f&&objs[j]->probability(slots[i].states[slots[i].num])>0.5&&slots[i].states[slots[i].num].t_warte+slots[i].states[slots[i].num].t_around>=(dir_dist(i,sh.dir))+GL_latence && slots[i].states[slots[i].num].t_s<=(LIFETIME-((int)(slots[i].states[slots[i].num].t_warte)+frame_number)%4)
							&& (bF||slots[i].states[slots[i].num].t_warte+slots[i].states[slots[i].num].t_around>0.9) ) {
							//you can only shoot one per time
							slots[i].states[slots[i].num].obj=objs[j];
							bool b=false;
							for(int k=0; k<slots[i].num; k++)
								if( abs(slots[i].states[k].get_min()-slots[i].states[slots[i].num].get_min())<1.f ) {
									if(slots[i].states[k].get_min()>slots[i].states[slots[i].num].get_min()) {
										slots[i].states[k]=slots[i].states[slots[i].num];
									}
									b=true;
									break;
								}
							if(b) continue;

							int n=0;
							while(objs[j]->states[n]) ++n;
							objs[j]->states[n]=&slots[i].states[slots[i].num];

							if(objs[j]->bMultiply&&slots[i].states[slots[i].num].t_s<35) {
								objs[j]->s_min=min(objs[j]->s_min,slots[i].states[slots[i].num].t_warte);
							}

							++slots[i].num;
							++n1;

						}
					}

					if(n2==0&&i==sh.dir) {
						objs[j]->dbg_around=slots[i].states[alt].t_around;
						objs[j]->dbg_s=slots[i].states[alt].t_s;
						objs[j]->dbg_warte=slots[i].states[alt].t_warte;
					}

					float t,t2=1000000;

					if(cp.force.x) {
						t=(511-cp.pos.x)/(float)cp.force.x;
						if(t>=0&&t>=0&&t<t2)
							t2=t;
						t=(-512-cp.pos.x)/(float)cp.force.x;
						if(t>=0&&t>=0&&t<t2)
							t2=t;
					}
					if(cp.force.y) {
					t=(383-cp.pos.y)/(float)cp.force.y;
					if(t>=0&&t<t2)
						t2=t;
						t=(-384-cp.pos.y)/(float)cp.force.y;
					if(t>=0&&t<t2)
						t2=t;
					}

					if(t2>100000||t2<0.f)
						break;

					time+=t2+8.f;
					cp.pos=cp.pos + cp.force*(t2+8.f);
				}
			}
			if(kann) 
				break;
		}

		int max_level=0;
		for(int i=0; i<num; i++) {
			if(objs[i]->shot_time<0) {
				float m=min_from_object(objs[i])+15;
				if(objs[i]->bMultiply&&objs[i]->s_min>70+m)
					objs[i]->level=1;
				float t1,t2;
				if(objs[i]->collidate(sh,t1,t2)) {
					if( (t1>0||t2>0)&&(t1<m||t2<m) )
						objs[i]->level=3;
				}
			}
			max_level=max(objs[i]->level,max_level);
		}

		int best_sl=-1,best_st=0;
		float best_v=0;
		Object *shoot=NULL;
		float time_shot=0.f;

		if(!kann) {
			best_sl=-1;
			if(num<115) {
				tree1(objs,num,best_sl,best_st,sh.dir,max_level);
				if(best_sl!=-1) {
					
		for(int s=0; s<slots[sh.dir].num&&bF; s++)
			if(slots[sh.dir].states[s].t_warte-GL_latence>-slots[sh.dir].states[s].t_around&&slots[sh.dir].states[s].t_warte-GL_latence<(slots[sh.dir].states[s].t_around)&&((best_sl==sh.dir&&s==best_st)||next_shots[0]<slots[best_sl].states[best_st].get_max()||slots[sh.dir].states[s].t_s<slots[best_sl].states[best_st].get_max())) {
				shoot=slots[sh.dir].states[s].obj;
				time_shot=1+slots[sh.dir].states[s].t_s;
				break;
			}
				}
			}
		if(best_sl==-1) 
		{
		//search min(t_warten+t_s)
		float min=100000.f;
		int sl=-1,st=-1;
		
		if(num<19) {
			for(int i=0; i<NUM_CIRCLE; i++) {
				for(int j=0; j<slots[i].num; j++) {
					if(slots[i].states[j].obj->level==max_level&&(slots[i].states[j].t_warte-slots[i].states[j].t_around*0.5>=next_shots[0]||next_shots[0]<0)&&slots[i].states[j].t_warte+(next_shots[0]<=slots[i].states[j].t_warte?0:slots[i].states[j].t_s)+(dir_dist(i,sh.dir))+GL_latence<min) {//&&slots[i].states[j].t_warte+(next_shots[0]<=slots[i].states[j].t_warte?0:slots[i].states[j].t_s)>0.2*slots[i].states[j].t_s) {
						min=slots[i].states[j].t_warte+(next_shots[0]<=slots[i].states[j].t_warte?0:slots[i].states[j].t_s)+(dir_dist(i,sh.dir))+GL_latence;
						best_sl=sl=i;
						best_st=st=j;
					}
				}
			}
		}
		else {
			for(int i=0; i<NUM_CIRCLE; i++) {
				for(int j=0; j<slots[i].num; j++) {
					if(slots[i].states[j].obj->level==max_level&&(slots[i].states[j].t_warte-slots[i].states[j].t_around*0.5>=next_shots[0]||next_shots[0]<0)&&slots[i].states[j].t_warte*slots[i].states[j].t_s+dir_dist(i,sh.dir)+GL_latence<min) {//&&slots[i].states[j].t_warte+(next_shots[0]<=slots[i].states[j].t_warte?0:slots[i].states[j].t_s)>0.2*slots[i].states[j].t_s) {
						min=slots[i].states[j].t_warte*slots[i].states[j].t_s+(dir_dist(i,sh.dir))+GL_latence;
						best_sl=sl=i;
						best_st=st=j;
					}
				}
			}
		}

		for(int s=0; s<slots[sh.dir].num&&bF&&sl!=-1; s++)
			if(slots[sh.dir].states[s].t_warte-GL_latence>-slots[sh.dir].states[s].t_around&&slots[sh.dir].states[s].t_warte-GL_latence<(slots[sh.dir].states[s].t_around)&&((sl==sh.dir&&s==st)||next_shots[1]<slots[sl].states[st].get_max()||slots[sh.dir].states[s].t_s<slots[sl].states[st].get_max())) {
				shoot=slots[sh.dir].states[s].obj;
				time_shot=1+slots[sh.dir].states[s].t_s;
				break;
			}

		}
		}

		if(kann) {
			for(int s=0; s<slots[sh.dir].num&&bF; s++)
				if(slots[sh.dir].states[s].t_warte-GL_latence>-slots[sh.dir].states[s].t_around&&slots[sh.dir].states[s].t_warte-GL_latence<(slots[sh.dir].states[s].t_around)) {
					shoot=slots[sh.dir].states[s].obj;
					time_shot=1+slots[sh.dir].states[s].t_s;
					break;
				}
		}

		bool bShoot=shoot?true:false;
		if(bShoot) {
			set_Shots(next_shots,time_shot);
			int b=0;
			while(shoot->states[b]) {
				if( shoot->states[b]->t_warte-GL_latence<(shoot->states[b]->t_around) ) {
					slots[shoot->states[b]->pos].min=time_shot;
				}
				++b;
				if(b>=NUM_CIRCLE*MAX_COVER) break;
			}

			shoot->setShot(time_shot);
		}

		if(!kann) {
		if(best_sl==-1)
			dur2=dur=0;
		else {
			dur=abs(best_sl-sh.dir);
			dur2=slots[best_sl].states[best_st].t_warte-slots[best_sl].states[best_st].t_around+1;
		}
		}

		if(num<1&&!bShoot&&next_shots[1]<0&&bF) {
			set_Shots(next_shots,72);
			return -1&(~2);
		}
		else if(num<1)
			return -1;

		if(best_sl==sh.dir||best_sl==-1||kann)
			return (bShoot?0:2);
		else if(dir_dist2(best_sl,sh.dir)>0)
			return -1&(~(bShoot?2:0));
		return 1|(bShoot?0:2);

	}
};