Esempio n. 1
0
float angle( LWFVector a, LWFVector b )
{
   LWFVector na, nb;

   copyv( na, a );
   normalize( na );
   copyv( nb, b );
   normalize( nb );
   return ( float ) acos( dot( na, nb ));
}
Esempio n. 2
0
//Funzione che genera tutte le permutazioni di un vettore di interi
void permute(int v[], int l, int r, int nmax){
	int i;
	int temp[nmax];
	
	if(l == r){
		enum_combo2(v, nmax);
		printvf(v, nmax, 0);
		
		//Copio il vettore in quello temporaneo
		copyv(v, temp, nmax);
		
		fprintf(f, " : ");
		
		//Stampo i cicli trovati dal cyclesort
		cyclesort(temp, nmax);
		
	}else{
		
		for(i=l;i<=r;i++){
			swap(v, l, i);
			permute(v, l+1, r, nmax);
			swap(v, l, i);
		}
	}
}
Esempio n. 3
0
static void prev_dog_bot(void)
{
    int DBi=DogBot;
    DogBotDist=0;
    do {
        if (--DogBot<0) DogBot=NBBOT-1;
        if (DogBot!=controlled_bot) {
            copyv(&DogBotDir,&obj[bot[DogBot].vion].pos);
            subv(&DogBotDir,&obj[bot[controlled_bot].vion].pos);
            DogBotDist=renorme(&DogBotDir);
        }
    } while (DogBot!=DBi && (DogBotDist>DOGDISTMAX || bot[DogBot].camp==-1 || DogBot==controlled_bot));
}
Esempio n. 4
0
void vec_hp( LWFVector a, float *h, float *p )
{
   LWFVector n;

   copyv( n, a );
   normalize( n );

   *p = ( float ) asin( -n[ 1 ] );
   if ( 1.0f - fabs( n[ 1 ] ) > EPSILON_F ) {
      *h = ( float )( acos( n[ 2 ] / cos( *p )));
      if ( n[ 0 ] < 0.0f )
         *h = ( float )( 2 * PI - *h );
   }
   else *h = 0.0f;
}
Esempio n. 5
0
matriz * gs(matriz &v){ //classico
	matriz * w = (matriz *) malloc(sizeof(matriz));
	w->l=v.l;
	w->c=v.c;
	for(int i=0;i<v.l;i++)
		copyv(w->vet[i],v.vet[i],v.c);
	for(int i=1;i<v.l;i++){
			long double valor = prodint(w->vet[i-1],w->vet[i],v.c);
			long double div = prodint(w->vet[i],w->vet[i],v.c);
			printf("%LF / %LF = ", valor,div);
				valor/=div;
				printf("%LF\n", valor);
				sumvet(w->vet[i],w->vet[i],prodext(w->vet[i],valor * -1,v.c),v.c); //soma Vk
	}

	return w;
}
Esempio n. 6
0
/*A problem found in alphabeta pruning is that once I get a 0 value for a certain MAX node (guaranteed draw) if any of the next nodes has a value of -1 alphabeta allocates it as a 0 value node. Although these children don't really affect the true value of father's alphabeta (as max node if there's a 0, it can't get less) it can happen that I have to count the number of winnning leaves and naturally I can't choose a path that seems 0 (draw) while it is indeed -1 (lose) so that I developed this function that returns the TRUE value of a certain node that normally is allocated as 0 but in reality can also be -1*/
static int TrueValue(NODE *T) {
	NODE *tmpSubTree; //temporarily to this function
	int valore;
	if ((tmpSubTree = (NODE*)malloc(sizeof(NODE))) == NULL) exit(0);

	tmpSubTree->depth = T->depth;
	tmpSubTree->i = T->i;
	tmpSubTree->j = T->j;
	tmpSubTree->leftchild = NULL;
	tmpSubTree->rightbrothers = NULL;
	tmpSubTree->player = T->player;
	tmpSubTree->value == (T->player == MAX) ? (-2) : (2);
	tmpSubTree->transboard = copyv(T->transboard);


	valore = alphabeta(&tmpSubTree, tmpSubTree->depth, -1, 1, tmpSubTree->player); //simply I recreate a sub-tree with the technique used to create the whole tree so that I get the TRUE value and I store it in the real tree
	DeleteTree(&tmpSubTree); //eventually I free tmpSubTree

	return (valore); //returns the TRUE value of that child
}
void main()
{
	const int nx = 1800;
	
	const double dx = 1.0/(double)nx;
	const double dt = 0.2*dx;
	const double k = 2.0*pow(dx,2.0)/dt;

	const	double S = 0.0;
	const double t0 = 0.0, TF = 0.76;

	double *pn, *pk, *pkm, *thetan, *thetak, *thetakm, *cm, *ckm;

	double t;

	double change; const double tol = 5E-8;

	double h, dhdt, h3;

	int ix;

	int PRINT_FREQ = 100000000;

	// MEMORY ALLOCATION
	pk = (double *) malloc(sizeof(double) * nx);
	pkm = (double *) malloc(sizeof(double) * nx);
	thetak = (double *) malloc(sizeof(double) * nx);
	thetakm = (double *) malloc(sizeof(double) * nx);
	cm = (double *) malloc(sizeof(double) * nx);
	ckm = (double *) malloc(sizeof(double) * nx);

	// INITIALIZATION
	for (ix=0; ix<nx; ix++){
		pk[ix] = 0.025;
		thetak[ix] = 1.0;
	}

	copyv(pkm,pk,nx,1.0);
	copyv(thetakm,thetak,nx,1.0);
	copyv(cm,thetak,nx,0.125*cos(4.0*PI*t0) + 0.375);
	copyv(ckm,cm,nx,1.0);

	int niter = 0;

	FILE *fsigma;
	fsigma = fopen("sigma_ea_1800.dat","w");

	double sigma = 0.0;
	int sigmai = 0;


	// TIME ITERATIONS
	while (t <= TF){

		niter += 1; t = t0 + dt*niter;

		h = 0.125*cos(4.0*PI*t) + 0.375;
		h3 = pow(h,3.0);

		change = tol + 1.0;
		while(change > tol) { //GAUSS-SEIDEL

			copyv(ckm,thetak,nx,h);
			
			for (ix=1;ix<nx-1;ix++){ //LOOP OVER NODES
				if (pkm[ix] > 0.0 || thetakm[ix] >= 1.0){

					pk[ix] = 0.5/h3*(S*dx*(ckm[ix-1]-ckm[ix]) - k*(ckm[ix]-cm[ix]) + h3*(pkm[ix+1] + pkm[ix-1]));

					if (pk[ix] >= 0.0) //cavitation check
						thetak[ix] = 1.0;
					else
						pk[ix] = 0.0;
				}

				if (pk[ix] <= 0.0 || thetak[ix] < 1.0){
					thetak[ix] = 1.0/(k+S*dx)/h*(k*cm[ix] + S*dx*ckm[ix-1] + h3*(pkm[ix+1]-2.0*pkm[ix]+pkm[ix-1]));

					if (thetak[ix] < 1.0 ) //cavitation check
						pk[ix] = 0.0;
					else
						thetak[ix] = 1.0;
				}	
			} //END LOOP OVER NODES

			change = norm2_dif(pkm,pk,nx) + norm2_dif(thetakm,thetak,nx);

			copyv(pkm,pk,nx,1.0); copyv(thetakm,thetak,nx,1.0);

		} //END GAUSS-SEIDEL

		copyv(cm,thetak,nx,h);

		printf("tn %1.3e h(t) %1.3f n %d\n",t,h,niter);

		if (niter % PRINT_FREQ == 0)
			print_to_file(pk, nx, niter);

		sigmai = 0;
		sigma = 0.0;

		for (ix=1;ix<nx-1;ix++)
			if (pk[ix]==0.0 && pk[ix+1] > 0.0)
				sigmai = ix;
		sigma = sigmai*dx;

		fprintf(fsigma, "%1.6e %1.6e\n", t, sigma);
			
	} //END while(t <= TF)

	fclose(fsigma);

	free(thetak); free(thetakm);
	free(pk); free(pkm); free(cm); free(ckm);

} 
Esempio n. 8
0
/*contains the call to alphabeta and the creation of the gametree*/
int get_next_move(unsigned int *i, unsigned int *j) {
		unsigned int x;

		/*Initially I consider the special cases*/
		if (C == M*N) {

			x = firstmove();
			*i = x / N;
			*j = x - N*(x / N);
			BOARD[*i][*j] = 1;


			C--;
			return 1;
		}

		if ((M == 4 && N == 4 && K == 4) && M*N - C == 2) { //4x4x4 and if M*N-C == 2 means that there have been only 2 total moves and this is currently the secondmove of player1

			x = secondmove();
			*i = x / N;
			*j = x - N*(x / N);
			BOARD[*i][*j] = 1;
			C--;
			return 1;
		}

		
		if ((M == 6 && N == 4 && K == 3) && M*N - C == 2) { //same with 6x4x3

			x = secondmove();
			*i = x / N;
			*j = x - N*(x / N);
			BOARD[*i][*j] = 1;
			C--;
			return 1;
		}
		
		if ((M == 5 && N == 5 && K == 3) && M*N - C == 2) { //same with 5x5x3

			x = secondmove();
			*i = x / N;
			*j = x - N*(x / N);
			BOARD[*i][*j] = 1;
			C--;
			return 1;
		}




		if (Z == 0) { 

			if ((GameTree = (NODE*)malloc(sizeof(NODE))) == NULL) { 
				printf("\nError");
				exit(0);
			}

			GameTree->depth = C;
			GameTree->i = tmpI;
			GameTree->j = tmpJ; 
			GameTree->player = MAX;
			GameTree->transboard = Trans();
			GameTree->leftchild = NULL;
			GameTree->rightbrothers = NULL;

			Z++;


			GameTree->value = alphabeta(&GameTree, GameTree->depth, -1, 1, GameTree->player); //I let alphabeta create all the game tree



	
			{ //right after being created
				NODE *scorri;


				if (GameTree->value == 1) { //if I fould the value to be 1 I can just follow the 1 path and it'll lead me to certain win
					for (scorri = GameTree->leftchild; scorri->value != GameTree->value; scorri = scorri->rightbrothers) //hence I'll just search among the children until I find the 1 value
						; 
					*i = scorri->i; 
					*j = scorri->j;
					C--; //decreasing the number of total moves left 
					BOARD[*i][*j] = 1; // updating BOARD...
				}
				
				
				else { //case value = 0 (it can't be -1 because since we're starting first there's no way, having the perfect strategy that we can lose, at least we can draw)
					NODE *tmp1;
					unsigned int maxwins = 0;
					for (tmp1 = GameTree->leftchild; tmp1 != NULL; tmp1 = tmp1->rightbrothers) { //among all children I check for the one with the highest win-coefficient (see explanation in CountWins), it'll be called MaxWins
						if (TrueValue(tmp1) == 0); //if value = 0(it can't be 1 otherwise Gametree's value wouldn't be 0) I also don't want to choose a losing path, even if it has the highest win coefficient
							maxwins = Max(maxwins, CountWins(tmp1)); 
					}


					if (maxwins != 0) { //se esistono vittorie possibili...
						for (tmp1 = GameTree->leftchild; maxwins != CountWins(tmp1) ||TrueValue(tmp1) != 0; tmp1 = tmp1->rightbrothers) 
							; 

					
					}

					else { //if instead there is no possible win (but I still can draw)
						for (tmp1 = GameTree->leftchild; TrueValue(tmp1) != 0; tmp1 = tmp1->rightbrothers)
							; //i just pick the first TrueValue = 0
					}
					*i = tmp1->i; //and i update the AI move
					*j = tmp1->j;
					C--;
					BOARD[*i][*j] = 1;
				
				}



				

			
		

				/*Deleting the part of tree that I won't use as before in set_opponent_move.*/

					NODE *canc = GameTree->leftchild, *prev = NULL;
					
					while (canc != NULL) {
						
						
						if (canc->i != *i || canc->j != *j) {
							if (prev == NULL) {
								GameTree->leftchild = canc->rightbrothers;
								DeleteTree(&canc);
								canc = GameTree->leftchild;
							}

							else {
								prev->rightbrothers = canc->rightbrothers;
								DeleteTree(&canc);
								canc = prev->rightbrothers;

							}
						}

						else {
							prev = canc;
							canc = canc->rightbrothers;
						}
					}

					GameTree = GameTree->leftchild;
				
				
			}
		}

		
		
		else { //If we already generated a GameTree
			NODE *tmp = GameTree;
			NODE *scorri;

		
			if (GameTree->value == 1) { //as before, if value = 1 then I can just pick the first child with value 1 and it'll lead me to certain win
				for (scorri = tmp->leftchild; scorri->value != 1; scorri = scorri->rightbrothers) {
					
				}
				/*Updating AI move*/
				*i = scorri->i;
				*j = scorri->j;
			}


			
			else if (GameTree->value == 0 && TrueValue(GameTree) == 1) { //it can happen that the original value of the gametree changes during the game (ex: non-optimal moves of the opponents) so that I always have to follow first a path that will lead to certain victory, if there is
				NODE *newGameTree, *scorri;
				
				
				if ((newGameTree = (NODE*)malloc(sizeof(NODE))) == NULL) exit(0); //creating a new winning gametree
				
				newGameTree->depth = GameTree->depth;
				newGameTree->i = GameTree->i;
				newGameTree->j = GameTree->j;
				newGameTree->leftchild = NULL;
				newGameTree->player = GameTree->player;
				newGameTree->transboard = copyv(GameTree->transboard);
				newGameTree->rightbrothers = NULL;

				DeleteTree(&GameTree);

				newGameTree->value = alphabeta(&newGameTree, newGameTree->depth, -1, 1, newGameTree->player); 
				GameTree = newGameTree;
				for (scorri = GameTree->leftchild; scorri->value != GameTree->value; scorri = scorri->rightbrothers) 
					;

				/*Updating the move*/
				*i = scorri->i;
				*j = scorri->j;

			}

				
			else { //as before if Gametree value = 0
					
				NODE *tmp;
				unsigned int maxwins = 0;

				for (tmp = GameTree->leftchild; tmp != NULL; tmp = tmp->rightbrothers) { //searching for the child with highest win-coefficient whose value isn't -1
					if (TrueValue(tmp) == 0)
						maxwins = Max(maxwins, CountWins(tmp));
				}



				if (maxwins != 0) { //if there are possible wins
					for (tmp = GameTree->leftchild; maxwins != CountWins(tmp) || TrueValue(tmp) != 0; tmp = tmp->rightbrothers)
						;
				}
				
				else { //if there aren't possible wins
					for (tmp = GameTree->leftchild; TrueValue(tmp) != 0; tmp = tmp->rightbrothers)
						; //i'll just take the first node with 0 value
				}
				/*updating AI move*/
				*i = tmp->i;
				*j = tmp->j;
				


			}

			/*deleting useless tree part*/
			
				NODE *canc = GameTree->leftchild, *prev = NULL;


				while (canc != NULL) {

					if (canc->i != *i || canc->j != *j) {
						if (prev == NULL) {
							GameTree->leftchild = canc->rightbrothers;
							DeleteTree(&canc);
							canc = GameTree->leftchild;
						}

						else {
							prev->rightbrothers = canc->rightbrothers;
							DeleteTree(&canc);
							canc = prev->rightbrothers;

						}
					}

					else {
						prev = canc;
						canc = canc->rightbrothers;
					}
				}

				GameTree = GameTree->leftchild; 
				
				
			C--;
			BOARD[*i][*j] = 1;
			



		}

		if (C == 0) //when we're finished I just free the whole memory used in the tree
			DeleteTree(&GameTree);

		return 1;
	}
Esempio n. 9
0
/*alphabeta pruning,  player.c's core, accurate description is inside the paper*/
static int  alphabeta(NODE **T, int depth, int a, int b, int maximizingPlayer) {


	if (depth == 0 || GetWin(*T)) { //if leaf...

		((*T)->player == MAX) ? ((*T)->value = -GetWin(*T)) : ((*T)->value = GetWin(*T)); //I assign a value to the node, -1 if opponent's win, +1 if AI win
		return (*T)->value;
	}

	if (maximizingPlayer == MAX) { //only if minimizing node

		NODE *tmp;
		unsigned short *v = NULL;
		unsigned int x, count;


		if (!AllocateChildren(T, depth, 0, 0, MIN, NULL)) { //first I allocate 1 child without giving any value, I do this to keep everything in one for-cycle

			printf("\nError");
			exit(0);
		}

		tmp = (*T)->leftchild;
		v = copyv((*T)->transboard); //I take the node's board and...
		for (x = 0, count = 0; x < M*N; x++) { //...I check every possibile move from that certain board state



			if (v[x] != 0) //if it's already occupied it's not an acceptable move so I go on
				continue;

			else {
				v[x] = maximizingPlayer; //I temporarily make a move on the free box (then it'll become empty once again)
				if (count == 0) { //means that I'm working with the first child, hence its address comes from the father and not from the brothers
					tmp->i = x / N; //saving the current move in the node
					tmp->j = x - N*(x / N);
					tmp->transboard = copyv(v); //and also the board
					count++; //increasing count in order not to belong to this case (first child) again
				}

				else { //if I already handled the first child

					if (!AllocateChildren(T, depth, x / N, x - N*(x / N), MIN, copyv(v))) { //I allocate the space for the brothers and their current values (board, i,j etc)

						printf("\nError");
						exit(0);
					}

					tmp = tmp->rightbrothers;
					count++;
				}

				tmp->value = Max(tmp->value, alphabeta(&tmp, depth - 1, a, b, maximizingPlayer == 1 ? 2 : 1)); //recursive call that goes to the other part (minimizing part) of the function (if father is maximizing then the children are minimizing because between father and children the player changes) 

				a = Max(a, tmp->value); //a is the best possible move for player1, so I have to choose the one with highest value
				v[x] = 0;
				if (a >= b) //pruning: if I see that the best possible move for player 1 has the same value of the best possibile move of player 2 I don't need to waste time to find another move nor to allocate more brothers
					break;



			}


		}

		return a;
	}




	else if (maximizingPlayer == MIN) { //same as above, just we're working with minimizing nodes

		NODE *tmp;
		unsigned short *v = NULL;
		unsigned int x, count;


		if (!AllocateChildren(T, depth, 0, 0, MAX, NULL)) {

			printf("\nError");
			exit(0);
		}

		tmp = (*T)->leftchild;
		v = copyv((*T)->transboard);
		for (x = 0, count = 0; x < M*N; x++) { //for every possible move...



			if (v[x] != 0)
				continue;

			else {
				v[x] = maximizingPlayer;
				if (count == 0) {
					tmp->i = x / N;
					tmp->j = x - N*(x / N);
					tmp->transboard = copyv(v);
					count++;
				}

				else {

					if (!AllocateChildren(T, depth, x / N, x - N*(x / N), MAX, copyv(v))) {

						printf("\nError");
						exit(0);
					}

					tmp = tmp->rightbrothers;
					count++;
				}

				tmp->value = Min(tmp->value, alphabeta(&tmp, depth - 1, a, b, maximizingPlayer == 1 ? 2 : 1)); //again, here the recursive call inverts minimizing with maximizing

				b = Min(b, tmp->value); //b instead chooses the minimum value because it has to pick the move that helps player1 less (=best move for player2 = optimal strategy)
				v[x] = 0;
				if (a >= b) //as before
					break;



			}


		}

		return b;
	}


}
Esempio n. 10
0
static void filter(VagueDenoiserContext *s, AVFrame *in, AVFrame *out)
{
    int p, y, x, i, j;

    for (p = 0; p < s->nb_planes; p++) {
        const int height = s->planeheight[p];
        const int width = s->planewidth[p];
        const uint8_t *srcp8 = in->data[p];
        const uint16_t *srcp16 = (const uint16_t *)in->data[p];
        uint8_t *dstp8 = out->data[p];
        uint16_t *dstp16 = (uint16_t *)out->data[p];
        float *output = s->block;
        int h_low_size0 = width;
        int v_low_size0 = height;
        int nsteps_transform = s->nsteps;
        int nsteps_invert = s->nsteps;
        const float *input = s->block;

        if (!((1 << p) & s->planes)) {
            av_image_copy_plane(out->data[p], out->linesize[p], in->data[p], in->linesize[p],
                                s->planewidth[p], s->planeheight[p]);
            continue;
        }

        if (s->depth <= 8) {
            for (y = 0; y < height; y++) {
                for (x = 0; x < width; x++)
                    output[x] = srcp8[x];
                srcp8 += in->linesize[p];
                output += width;
            }
        } else {
            for (y = 0; y < height; y++) {
                for (x = 0; x < width; x++)
                    output[x] = srcp16[x];
                srcp16 += in->linesize[p] / 2;
                output += width;
            }
        }

        while (nsteps_transform--) {
            int low_size = (h_low_size0 + 1) >> 1;
            float *input = s->block;
            for (j = 0; j < v_low_size0; j++) {
                copy(input, s->in + NPAD, h_low_size0);
                transform_step(s->in, s->out, h_low_size0, low_size, s);
                copy(s->out + NPAD, input, h_low_size0);
                input += width;
            }

            low_size = (v_low_size0 + 1) >> 1;
            input = s->block;
            for (j = 0; j < h_low_size0; j++) {
                copyv(input, width, s->in + NPAD, v_low_size0);
                transform_step(s->in, s->out, v_low_size0, low_size, s);
                copyh(s->out + NPAD, input, width, v_low_size0);
                input++;
            }

            h_low_size0 = (h_low_size0 + 1) >> 1;
            v_low_size0 = (v_low_size0 + 1) >> 1;
        }

        if (s->method == 0)
            hard_thresholding(s->block, width, height, width, s->threshold, s->percent);
        else if (s->method == 1)
            soft_thresholding(s->block, width, height, width, s->threshold, s->percent, s->nsteps);
        else
            qian_thresholding(s->block, width, height, width, s->threshold, s->percent);

        s->hlowsize[0]  = (width + 1) >> 1;
        s->hhighsize[0] = width >> 1;
        s->vlowsize[0]  = (height + 1) >> 1;
        s->vhighsize[0] = height >> 1;

        for (i = 1; i < s->nsteps; i++) {
            s->hlowsize[i]  = (s->hlowsize[i - 1] + 1) >> 1;
            s->hhighsize[i] = s->hlowsize[i - 1] >> 1;
            s->vlowsize[i]  = (s->vlowsize[i - 1] + 1) >> 1;
            s->vhighsize[i] = s->vlowsize[i - 1] >> 1;
        }

        while (nsteps_invert--) {
            const int idx = s->vlowsize[nsteps_invert] + s->vhighsize[nsteps_invert];
            const int idx2 = s->hlowsize[nsteps_invert] + s->hhighsize[nsteps_invert];
            float * idx3 = s->block;
            for (i = 0; i < idx2; i++) {
                copyv(idx3, width, s->in + NPAD, idx);
                invert_step(s->in, s->out, s->tmp, idx, s);
                copyh(s->out + NPAD, idx3, width, idx);
                idx3++;
            }

            idx3 = s->block;
            for (i = 0; i < idx; i++) {
                copy(idx3, s->in + NPAD, idx2);
                invert_step(s->in, s->out, s->tmp, idx2, s);
                copy(s->out + NPAD, idx3, idx2);
                idx3 += width;
            }
        }

        if (s->depth <= 8) {
            for (y = 0; y < height; y++) {
                for (x = 0; x < width; x++)
                    dstp8[x] = av_clip_uint8(input[x] + 0.5f);
                input += width;
                dstp8 += out->linesize[p];
            }
        } else {
            for (y = 0; y < height; y++) {
                for (x = 0; x < width; x++)
                    dstp16[x] = av_clip(input[x] + 0.5f, 0, s->peak);
                input += width;
                dstp16 += out->linesize[p] / 2;
            }
        }
    }
}
Esempio n. 11
0
void control(int b)
{
    struct vector u;
    // Left button
    if (! map_mode) switch (selected_weapon) {
    case 0:
        if ((enable_mouse && button_read(SDL_BUTTON_LEFT)) || kread(gkeys[kc_fire].kc)) bot[b].but.canon=1;
        break;
    case 1:
        if ((enable_mouse && button_reset(SDL_BUTTON_LEFT)) || kreset(gkeys[kc_fire].kc)) bot[b].but.bomb=1;
        break;
    } else if ((enable_mouse && button_read(SDL_BUTTON_LEFT)) || kread(gkeys[kc_fire].kc)) {
        bot[b].u.x = ((xmouse-win_center_x)*(MAP_LEN/2)*TILE_LEN)/zoom+map_x*TILE_LEN;
        bot[b].u.y = ((win_center_y-ymouse)*(MAP_LEN/2)*TILE_LEN)/zoom+map_y*TILE_LEN;
        bot[b].u.z = z_ground(bot[b].u.x, bot[b].u.y, true);
    }
    // Right button
    if ((enable_mouse && button_reset(SDL_BUTTON_RIGHT)) || kreset(gkeys[kc_weapon].kc)) {
        if (abs(xmouse) < 2 && abs(ymouse) < 2) {
            if (! prompt_quit) prompt_quit = true;
            else quit_game = true;
        }
        selected_weapon ^= 1;
    }
    // Esc
    if (prompt_quit) {
        if (kreset(gkeys[kc_yes].kc)) quit_game = true;
        if (kreset(gkeys[kc_no].kc)) prompt_quit = false;
    } else if (kreset(gkeys[kc_esc].kc) && (bot[controlled_bot].camp!=-1 || !enable_resurrection || !resurrect())) {
        prompt_quit = true;
    }

    // Engine
#   define INCR .02
    if (kread(gkeys[kc_motormore].kc) && bot[b].thrust <= 1.-INCR) bot[b].thrust += INCR;
    if (kread(gkeys[kc_motorless].kc) && bot[b].thrust >= INCR) bot[b].thrust -= INCR;
#   undef INCR
    // Views
    if (kreset(gkeys[kc_externview].kc)) {
        map_mode = false;
        view = next_external_view(view);
        snd_thrust=-1;
    }
    if (kreset(gkeys[kc_internview].kc)) {
        map_mode = false;
        if (view == VIEW_IN_PLANE) {
            view = VIEW_DOGFIGHT;
        } else {
            view = VIEW_IN_PLANE;
            snd_thrust=-1;
        }
    }
    if (kreset(gkeys[kc_travelview].kc)) {
        float zs;
        map_mode = false;
        view = VIEW_STANDING;
        copyv(&obj[0].pos,&obj[bot[viewed_bot].vion].rot.x);
        mulv(&obj[0].pos,300+drand48()*600+extcam_dist);
        copyv(&u,&obj[bot[viewed_bot].vion].rot.y);
        mulv(&u,(drand48()-.5)*600);
        addv(&obj[0].pos,&u);
        copyv(&u,&obj[bot[viewed_bot].vion].rot.z);
        mulv(&u,(drand48()-.5)*600);
        addv(&obj[0].pos,&u);
        addv(&obj[0].pos,&obj[bot[viewed_bot].vion].pos);
        if (obj[0].pos.z<(zs=z_ground(obj[0].pos.x,obj[0].pos.y, false)+100)) obj[0].pos.z=zs;
        snd_thrust=-1;
    }
    if (kreset(gkeys[kc_nextbot].kc)) {
        if (view == VIEW_ANYTHING_CHEAT) {
            if (++viewed_obj >= nb_obj) viewed_obj = 0;
        } else if (view == VIEW_DOGFIGHT) {
            next_dog_bot();
        } else {
            do {
                if (++viewed_bot>=NBBOT) viewed_bot=0;
            } while (!enable_view_enemy && bot[viewed_bot].camp!=camp);  // pas controlled_bot.camp car peut etre tue
            snd_thrust=-1;
            if (bot[viewed_bot].camp==-1) playsound(VOICE_MOTOR, SAMPLE_FEU, 1., &voices_in_my_head, true, true);
        }
    }
    if (kreset(gkeys[kc_prevbot].kc)) {
        if (view == VIEW_ANYTHING_CHEAT) {
            if (--viewed_obj<0) viewed_obj = nb_obj-1;
        } else if (view == VIEW_DOGFIGHT) {
            prev_dog_bot();
        } else {
            do {
                if (--viewed_bot<0) viewed_bot=NBBOT-1;
            } while (!enable_view_enemy && bot[viewed_bot].camp!=camp);
            snd_thrust=-1;
            if (bot[viewed_bot].camp==-1) playsound(VOICE_MOTOR, SAMPLE_FEU, 1., &voices_in_my_head, true, true);
        }
    }
    if (kreset(gkeys[kc_mybot].kc)) {
        if (view != VIEW_DOGFIGHT) {
            viewed_bot = b;
            snd_thrust = -1;
        } else {
            float d;
            int DBi, DBm;
            next_dog_bot();
            d=DogBotDist;
            DBi=DogBot; DBm=DogBot;
            do {
                next_dog_bot();
                if (DogBotDist<d && bot[DogBot].camp!=bot[controlled_bot].camp) {
                    d=DogBotDist;
                    DBm=DogBot;
                }
            } while (DogBot!=DBi);
            DogBot=DBm; DogBotDist=d;
        }
    }
    if (!accelerated_mode || frame_count > 64) {
        if (kread(gkeys[kc_zoomout].kc)) {
            if (! map_mode) extcam_dist += 10.;
            else zoom += win_center_x/6;
        }
        if (kread(gkeys[kc_zoomin].kc)) {
            if (! map_mode && extcam_dist > 10.) extcam_dist -= 10.;
            else if ((zoom -= win_center_x/6) < win_center_x) zoom = win_center_x;
        }
        if (kread(gkeys[kc_riseview].kc)) {
            if (! map_mode) {
                if ((sight_teta -= .2) < -M_PI) sight_teta += 2*M_PI;
            } else if ((map_y += 1 + (3*win_width)/zoom) > MAP_LEN/2) {
                map_y = MAP_LEN/2;
            }
        }
        if (kread(gkeys[kc_lowerview].kc)) {
            if (! map_mode) {
                if ((sight_teta += .2) > M_PI) sight_teta -= 2*M_PI;
            } else if ((map_y -= 1 + (3*win_width)/zoom) < -MAP_LEN/2) {
                map_y = -MAP_LEN/2;
            }
        }
        if (kread(gkeys[kc_rightenview].kc)) {
            if (! map_mode) {
                if ((sight_phi -= .2) < -M_PI) sight_phi += 2*M_PI;
            } else if ((map_x += 1 + (3*win_width)/zoom) > MAP_LEN/2) {
                map_x = MAP_LEN/2;
            }
        }
        if (kread(gkeys[kc_leftenview].kc)) {
            if (! map_mode) {
                if ((sight_phi += .2) > M_PI) sight_phi -= 2*M_PI;
            } else if ((map_x -= 1 + (3*win_width)/zoom) < -MAP_LEN/2) {
                map_x = -MAP_LEN/2;
            }
        }
    }
    if (view != VIEW_DOGFIGHT) {
        if (kreset(gkeys[kc_towardview].kc)) { sight_teta = sight_phi = 0; }
        if (kreset(gkeys[kc_backview].kc)) { sight_teta = 0; sight_phi = M_PI; }
        if (kreset(gkeys[kc_leftview].kc)) { sight_teta = 0; sight_phi = M_PI*.5; }
        if (kreset(gkeys[kc_rightview].kc)) { sight_teta = 0; sight_phi = -M_PI*.5; }
        if (kreset(gkeys[kc_upview].kc)) { sight_teta = -M_PI/2; sight_phi = 0; }
    } else {
        view_predef = false;
        if (kread(gkeys[kc_towardview].kc)) { view_predef = true; sight_teta = sight_phi = 0; }
        if (kread(gkeys[kc_backview].kc)) { view_predef = true; sight_teta = 0; sight_phi = M_PI; }
        if (kread(gkeys[kc_leftview].kc)) { view_predef = true; sight_teta = 0; sight_phi = M_PI*.5; }
        if (kread(gkeys[kc_rightview].kc)) { view_predef = true; sight_teta = 0; sight_phi = -M_PI*.5; }
        if (kread(gkeys[kc_upview].kc)) { view_predef = true; sight_teta = -M_PI/2; sight_phi = 0; }
        if (! view_predef) sight_teta = sight_phi = 0;
    }
    view_instruments = kread(gkeys[kc_movetowardview].kc);
    // Commands
    if (kreset(gkeys[kc_gear].kc)) bot[b].but.gear^=1;
    if (kreset(gkeys[kc_flaps].kc)) {
        bot[b].but.flap^=1;
        playsound(VOICE_GEAR, SAMPLE_BIPBIP, 1., &obj[bot[b].vion].pos, false, false);
    }
    bot[b].but.brakes=kread(gkeys[kc_brakes].kc);
    if (kreset(gkeys[kc_business].kc)) bot[b].but.business = 1;
    if (kreset(gkeys[kc_autopilot].kc)) {
        autopilot = ! autopilot;
        playsound(VOICE_GEAR, SAMPLE_BIPBIP, 1., &obj[bot[b].vion].pos, false, false);
        if (autopilot) {
            bot[controlled_bot].target_speed = BEST_SPEED_FOR_CONTROL;
            bot[controlled_bot].target_rel_alt = 100. * ONE_METER;
        }
    }
    // Game control
    if (kreset(gkeys[kc_pause].kc)) {
        gtime_toggle();
        game_paused = ! game_paused;
    }
    draw_high_scores = kread(gkeys[kc_highscores].kc);
    if (kreset(gkeys[kc_accelmode].kc)) { accelerated_mode = ! accelerated_mode; frame_count&=63; }
    if (kreset(gkeys[kc_basenav].kc)) {
        bot[b].u = obj[bot[b].babase].pos;
    }
    if (kreset(gkeys[kc_mapmode].kc)) {
        map_mode = ! map_mode;
        playsound(VOICE_GEAR, SAMPLE_BIPBIP3, 1., &voices_in_my_head, true, false);
    }
    if (kreset(gkeys[kc_suicide].kc) && bot[controlled_bot].camp!=-1) explode(bot[viewed_bot].vion, 0, "commited suicide");
    if (kreset(gkeys[kc_markpos].kc)) bot[b].but.mark=1;
    // Cheats
    if (cheat_mode && kread(gkeys[kc_alti].kc)) {
        obj[bot[viewed_bot].vion].pos.z += 500;
        bot[viewed_bot].vionvit.z = 0;
    }
    if (cheat_mode && kreset(gkeys[kc_gunned].kc)) bot[viewed_bot].gunned=controlled_bot;
    if (!autopilot && !map_mode) {
        if (enable_mouse) {
            bot[b].xctl = ((xmouse-win_center_x)/(double)win_center_x);
            bot[b].yctl = ((ymouse-win_center_y)/(double)win_center_y);
        } else {
            int i=0;
            i=kread(gkeys[kc_left].kc);
            i+=kread(gkeys[kc_right].kc)<<1;
            i+=kread(gkeys[kc_down].kc)<<2;
            i+=kread(gkeys[kc_up].kc)<<3;
            if (i) {
                CtlSensActu += CtlSensitiv;
                if (i&1) bot[b].xctl-=CtlSensActu;
                if (i&2) bot[b].xctl+=CtlSensActu;
                if (i&4) bot[b].yctl-=CtlSensActu;
                if (i&8) bot[b].yctl+=CtlSensActu;
            } else CtlSensActu=0;
            if (bot[b].xctl<-1 || bot[b].xctl>1 || bot[b].yctl<-1 || bot[b].yctl>1) CtlSensActu=0;
            if (!(i&3)) bot[b].xctl*=CtlAmortis;
            if (!(i&12)) bot[b].yctl=CtlYequ+(bot[b].yctl-CtlYequ)*CtlAmortis;
            if (kread(gkeys[kc_center].kc)) {
                bot[b].xctl=0;
                bot[b].yctl=CtlYequ;
                if (kread(gkeys[kc_down].kc) && CtlYequ>-1) CtlYequ-=.02;
                if (kread(gkeys[kc_up].kc) && CtlYequ<1) CtlYequ+=.02;
            }
        }
    } else {    // autopilot or map_mode
        if (autopilot) {
            robot_autopilot(b);
        } else {
            robot_safe(b, SAFE_LOW_ALT);
        }
    }
    CLAMP(bot[b].xctl, 1.);
    CLAMP(bot[b].yctl, 1.);
}