示例#1
0
inline void enPassantMoveDo(Position* position, const Move move){
	guint piece, capture, cSquare, color;
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	if(to < a4){
		color = Black;
		piece = Black_Pawn;
		capture = White_Pawn;
		cSquare = to+8;
	}
	else{
		color = White;
		piece = White_Pawn;
		capture = Black_Pawn;
		cSquare = to-8;
	}
	guint64 bitMove = 1ull<<from | 1ull<<to;
	guint64 bitCapture = 1ull<<cSquare;
	position->piece[color] ^= bitMove;
	position->piece[piece] ^= bitMove;
	position->piece[color^1] ^= bitCapture;
	position->piece[capture] ^= bitCapture;
	position->allPieces ^= bitMove | bitCapture;
	position->key ^= squareKey[piece][from] ^ squareKey[piece][to] ^ squareKey[capture][cSquare];
	position->type[from] = Empty;
	position->type[to] = piece;
	position->type[cSquare] = Empty;
	position->pvt[Opening] += pvt[piece][to][Opening]-pvt[piece][from][Opening]-pvt[capture][cSquare][Opening];
	position->pvt[Endgame] += pvt[piece][to][Endgame]-pvt[piece][from][Endgame]-pvt[capture][cSquare][Endgame];
	position->material[color^1] -= Pawn_Value;
	position->staticMoves = 0;
}
示例#2
0
inline void promoteMoveUndo(Position* position, const Move move, const guint promote){
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	guint piece, pPiece, capture, color;
	if(to>a4){
		color = White;
		piece = White_Pawn;
		pPiece = promote + White; 	
	}
	else{
		color = Black;
		piece = Black_Pawn;
		pPiece = promote + Black; 	
	}
	guint64 bitFrom = 1ull<<from;
	guint64 bitTo = 1ull<<to;
	position->piece[color] ^= bitFrom | bitTo;
	position->piece[piece] ^= bitFrom;
	position->piece[pPiece] ^= bitTo;
	position->allPieces ^= bitFrom | bitTo;
	position->type[from] = piece;
	position->type[to] = Empty;
	capture = position->capture;
	if(capture != Empty){
		position->type[to] = capture;
		position->piece[color^1] ^= bitTo;
		position->piece[capture] ^= bitTo;
		position->allPieces ^= bitTo;
	}
}
示例#3
0
inline void enPassantMoveUndo(Position* position, const Move move){
	guint piece, capture, cSquare, color;
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	if(to < a4){
		color = Black;
		piece = Black_Pawn;
		capture = White_Pawn;
		cSquare = to+8;
	}
	else{
		color = White;
		piece = White_Pawn;
		capture = Black_Pawn;
		cSquare = to-8;
	}
	guint64 bitMove = 1ull<<from | 1ull<<to;
	guint64 bitCapture = 1ull<<cSquare;
	position->piece[color] ^= bitMove;
	position->piece[piece] ^= bitMove;
	position->piece[color^1] ^= bitCapture;
	position->piece[capture] ^= bitCapture;
	position->allPieces ^= bitMove | bitCapture;
	position->type[from] = piece;
	position->type[to] = Empty;
	position->type[cSquare] = capture;
}
示例#4
0
inline void normalMoveUndo(Position* position, const Move move){
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	guint piece = position->type[to];
	guint color = piece % 2;
	guint64 bitMove = 1ull << from | 1ull << to;
	position->piece[color] ^= bitMove;
	position->piece[piece] ^= bitMove;
	position->allPieces ^= bitMove;
	position->type[from] = piece;
	position->type[to] = Empty;
}
示例#5
0
inline void captureMoveUndo(Position* position, const Move move){
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	guint piece = position->type[to];
	guint capture = position->capture;
	guint color = piece % 2;
	guint64 bitTo = 1ull << to;
	guint64 bitMove = 1ull<<from | bitTo;
	position->piece[color] ^= bitMove;
	position->piece[piece] ^= bitMove;
	position->piece[color^1] ^= bitTo;
	position->piece[capture] ^= bitTo;
	position->allPieces ^= 1ull << from;
	position->type[from] = piece;
	position->type[to] = capture;
}
示例#6
0
inline void castleMoveUndo(Position* position, const Move move){
	guint piece, rook, rFrom, rTo, color;
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	if(to < a4){
		color = White;
		piece = White_King;
		rook = White_Rook;
		if(to > e1){
			rFrom = h1;
			rTo = f1;
		}
		else{
			rFrom = a1;
			rTo = d1;
		}
	}
	else{
		color = Black;
		piece = Black_King;
		rook = Black_Rook;
		if(to > e8){
			rFrom = h8;
			rTo = f8;
		}
		else{
			rFrom = a8;
			rTo = d8;
		}
	}
	guint64 bitMove = 1ull<<from | 1ull<<to;
	guint64 bitRook = 1ull<<rFrom | 1ull<<rTo;
	position->piece[color] ^= bitMove | bitRook;
	position->piece[piece] ^= bitMove;
	position->piece[rook] ^= bitRook;
	position->allPieces ^= bitMove | bitRook;
	position->type[from] = piece;
	position->type[to] = Empty;
	position->type[rFrom] = rook;
	position->type[rTo] = Empty;
}
示例#7
0
gint threadSearch(Position* position, gint alpha, gint beta, gint depth, gint hight, const gboolean nullMove, const gboolean nodePV){
	Moves moves;
	Move move, bestMove = Empty, hMove = Empty, pMove=Empty;
	gboolean extend=FALSE, endGamePhase;
	gint eval, tmpDepth, movesSearched = 0, pAlpha, pType;
	guint idleThreads;
	guint64 key = position->key, hData;
	HashData* hd;

	if(stopFlag == TRUE && !ponderSearch) return EVAL_DRAW;

	searchNodes++;

	/* Draw */
	if(positionRepeat(position) >= 1 || position->staticMoves >= 100) return EVAL_DRAW;

	/* End game */
	gint numberOfPieces = numberOfBits64(position->allPieces);
	if(numberOfPieces <= 5 && egbbIsLoaded()){
		tmpDepth = (2 * iterativeDepth) / 3;
		if((numberOfPieces <= 4 || hight <= tmpDepth) &&
			(hight >= tmpDepth || positionEvalEG(position))){
			if(egbbProbe(position, &eval)){
				if(eval < 0) return eval + hight * 40 + positionMaterial(position);
				if(eval > 0) return eval - hight * 40 + positionMaterial(position);
				return eval;
			}
		}
	}

	/* Mate distance pruning */
	eval = -EVAL_MATE + hight;
	if(eval > alpha){
		if(eval >= beta) return eval;
		alpha = eval;
	}

	eval = EVAL_MATE - hight;
	if(eval < beta){
		if(eval <= alpha) return eval;
		beta = eval;
	}

	/* Hash */
	if(hashFind(&hd,key,&hData)){
		hMove = hashMove(hData);
        if(!nodePV && (gint)hashDepth(hData) >= depth){
			if(hashFlag(hData) == EXACT) return hashEval(hData);
			else if(hashFlag(hData) == ALPHA && hashEval(hData) > alpha){
				bestMove = hashMove(hData);
				alpha = hashEval(hData);
                if(alpha >= beta) return alpha;
			}
			else if(hashFlag(hData) == BETA && hashEval(hData) < beta){
				beta = hashEval(hData);
				if(alpha >= beta) return beta;
			}
		}
	}

	/* Extension */	
	if(position->extend || (nodePV && passedPawnMove(position))){
		depth ++;
		extend = TRUE;
	}

	/* Horizon */
	if(depth < 1){
		eval = quiescent(position,alpha,beta,hight+1,TRUE);
		return eval;
	}

	if(position->phase <= 7 && numberOfPieces <= 10) endGamePhase = TRUE;
	else endGamePhase = FALSE;

	/* Null move pruning */
	if (!nodePV && nullMove && depth>2 && !extend && !endGamePhase){
		if(depth > 6) tmpDepth = depth - 4;
		else tmpDepth = depth - 3;
		moveDo(position,Null_Move);
		eval = -threadSearch(position,-beta,-beta+1,tmpDepth,hight+1,FALSE,FALSE);
		moveUndo(position);
		if(eval >= beta){
			hashWrite(hd,key,depth,eval,ALPHA,Empty);
			return eval;
		}
	}

	/* Internal Iterative Deepening */
	tmpDepth = depth/2;
	if(nodePV && hMove == Empty && depth > 3 && tmpDepth >= (gint)hashDepth(hData)){
		threadSearch(position,alpha, beta, tmpDepth, hight, FALSE,nodePV);
		if(hashFind2(hd,key,&hData)) hMove = hashMove(hData);
	}

	/* First move */
	moves.state = START;
	if(hMove != Empty){
		move = hMove;
		moveDo(position,move);
	}
	else move = nextMoveDo(position,&moves);
	
	if(move != Empty){
		eval = -threadSearch(position, -beta, -alpha, depth-1, hight+1, TRUE,nodePV);
		if(eval > alpha){
			if(eval >= beta){
				moveUndo(position);
				if(moves.state == STATIC) history[moveGetFrom(move)][moveGetTo(move)] += 1<<depth;
				hashWrite(hd,key,depth,eval,ALPHA,move);
				return eval;
			}
			alpha = eval;
			bestMove = move;
		}
		moveUndo(position);
		movesSearched ++;
	}

	/* Parallel search*/
	idleThreads = searchThreads;

	while(TRUE){
		if(idleThreads > 0){
			move = nextMoveDo(position,&moves);
			/* Last moves searched sequential */
			if(move == Empty){
				parallelStopFlag = TRUE;
				moves.size = moves.next = 0;
				while(idleThreads != searchThreads){
					parallelSearchResult(&pMove,&pAlpha,&pType);
					idleThreads++;
					moves.move[moves.size] = pMove;
					moves.size ++;
				}
				parallelStopFlag = FALSE;
				moves.toSort = moves.size;
				break;
			}
			/* History pruning */
			if(!nodePV && movesSearched >= HistoryFullDepthMoves && depth > HistoryReductionLimit && 
				!extend && !position->extend){
				idleThreads--;
				parallelSearch(position, move, -(alpha+1), -alpha, depth-2, hight+1,TRUE,HP,FALSE);
				moveUndo(position);
				movesSearched ++;
			}
			else{ /* PVS */
				idleThreads--;
				parallelSearch(position, move, -(alpha+1), -alpha, depth-1, hight+1,TRUE,PVS,FALSE);
				moveUndo(position);
				movesSearched ++;
			}
		}
		else{
			eval = -parallelSearchResult(&pMove,&pAlpha,&pType);
			idleThreads++;
			pAlpha = -pAlpha - 1;
			if(pType == HP && eval > pAlpha){ /* HP */
				idleThreads--;
				moveDo(position,pMove);
				parallelSearch(position, pMove, -(pAlpha+1), -pAlpha, depth-1, hight+1,TRUE,PVS,FALSE);
				moveUndo(position);
				continue;
			}
			if(pType == PVS && eval > pAlpha && eval < beta){ /* PVS research */
				idleThreads--;
				moveDo(position,pMove);
				parallelSearch(position, pMove, -beta, -pAlpha, depth-1, hight+1,TRUE,RPVS,nodePV);
				moveUndo(position);
				continue;
			}
			if(eval > alpha){
				if(eval >= beta){
					parallelSearchStop(idleThreads);
					if(moveGetType(pMove) == Normal) history[moveGetFrom(pMove)][moveGetTo(pMove)] += 1<<depth;
					hashWrite(hd,key,depth,eval,ALPHA,pMove);
					return eval;
				}
				alpha = eval;
				bestMove = pMove;
			}
		}
	}

	/* Last moves searched sequential */
	move = nextMoveDo(position,&moves);
	while(move != Empty){
		/* History pruning */
		if(!nodePV && movesSearched >= HistoryFullDepthMoves && depth > HistoryReductionLimit && 
			!extend && !position->extend){
			eval = -threadSearch(position, -(alpha+1), -alpha, depth-2, hight+1, TRUE, FALSE);
		}
		else eval = alpha + 1;

		/* PVS */
		if(eval > alpha){
			eval = -threadSearch(position, -(alpha+1), -alpha, depth-1, hight+1, TRUE, FALSE);
			if(eval > alpha && eval < beta)
				eval = -threadSearch(position, -beta, -alpha, depth-1, hight+1, TRUE, nodePV);
		}
		moveUndo(position);
		if(eval > alpha){
			if(eval >= beta){
				if(moveGetType(pMove) == Normal) history[moveGetFrom(move)][moveGetTo(move)] += 1<<depth;
				hashWrite(hd,key,depth,eval,ALPHA,move);
				return eval;
			}
			alpha = eval;
			bestMove = move;
		}
		movesSearched ++;
		move = nextMoveDo(position,&moves);
	}

	/* Mate or pat */
	if(movesSearched == 0){
		if(position->inCheck == TRUE){
			eval = -EVAL_MATE+hight;
			hashWrite(hd,key,depth,eval,EXACT,Empty);
			return eval;
		}
		else{  
			hashWrite(hd,key,depth,EVAL_DRAW,EXACT,Empty);
			return EVAL_DRAW;
		}
	}

	/* hash is update */
	if(bestMove != Empty) hashWrite(hd,key,depth,alpha,EXACT,bestMove);
	else hashWrite(hd,key,depth,alpha,BETA,hMove);

	return alpha;
}
示例#8
0
inline void promoteMoveDo(Position* position, const Move move, const guint promote){
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	guint piece, pPiece, capture, color;
	capture = position->type[to];
	if(to>a4){
		color = White;
		piece = White_Pawn;
		pPiece = promote + White; 	
	}
	else{
		color = Black;
		piece = Black_Pawn;
		pPiece = promote + Black; 	
	}
	guint64 bitFrom = 1ull<<from;
	guint64 bitTo = 1ull<<to;
	position->piece[color] ^= bitFrom | bitTo;
	position->piece[piece] ^= bitFrom;
	position->piece[pPiece] ^= bitTo;
	position->allPieces ^=  bitFrom | bitTo;
	position->key ^= squareKey[piece][from] ^ squareKey[pPiece][to];
	position->type[from] = Empty;
	position->type[to] = pPiece;
	position->pvt[Opening] += pvt[pPiece][to][Opening] - pvt[piece][from][Opening];
	position->pvt[Endgame] += pvt[pPiece][to][Endgame] - pvt[piece][from][Endgame];
	position->material[color] += pieceValue[pPiece] - Pawn_Value;
	position->staticMoves = 0;
	position->phase += piecePhase[promote];
	if(capture != Empty){
		if(color == White){
			if(position->castle & BLACK_CASTLE){
				if(position->castle & BLACK_KING_CASTLE){
					if(to == h8){
						position->key ^= castleKey[Black_King_Castle];
						position->castle &= ~BLACK_KING_CASTLE;
					}
				}
				if(position->castle & BLACK_QUEEN_CASTLE){
					if(to == a8){
						position->key ^= castleKey[Black_Queen_Castle];
						position->castle &= ~BLACK_QUEEN_CASTLE;
					}
				}
			}
		}
		else{
			if(position->castle & WHITE_CASTLE){
				if(position->castle & WHITE_KING_CASTLE){
					if(to == h1){
						position->key ^= castleKey[White_King_Castle];
						position->castle &= ~WHITE_KING_CASTLE;
					}
				}
				if(position->castle & WHITE_QUEEN_CASTLE){
					if(to == a1){
						position->key ^= castleKey[White_Queen_Castle];
						position->castle &= ~WHITE_QUEEN_CASTLE;
					}
				}
			}
		}
		position->capture = capture;
		position->piece[color^1] ^= bitTo;
		position->piece[capture] ^= bitTo;
		position->allPieces ^= bitTo;
		position->key ^= squareKey[capture][to];
		position->pvt[Opening] -= pvt[capture][to][Opening];
		position->pvt[Endgame] -= pvt[capture][to][Endgame];
		position->material[color^1] -= pieceValue[capture];
		position->extend = TRUE;
	}
}
示例#9
0
inline gboolean castleMoveDo(Position* position, const Move move){
	guint piece, rook, rFrom, rTo, color;
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	if(to < a4){
		if(to > e1){
			if(!whiteCastleKingSide(position)) return FALSE;
			rFrom = h1;
			rTo = f1;
		}
		else{
			if(!whiteCastleQueenSide(position)) return FALSE;
			rFrom = a1;
			rTo = d1;
		}
		if(position->castle & WHITE_KING_CASTLE){
			position->key^= castleKey[White_King_Castle];
			position->castle &= ~WHITE_KING_CASTLE;
		}
		if(position->castle & WHITE_QUEEN_CASTLE){
			position->key^= castleKey[White_Queen_Castle];
			position->castle &= ~WHITE_QUEEN_CASTLE;
		}
		color = White;
		piece = White_King;
		rook = White_Rook;
	}
	else{
		if(to > e8){
			if(!blackCastleKingSide(position)) return FALSE;
			rFrom = h8;
			rTo = f8;
		}
		else{
			if(!blackCastleQueenSide(position)) return FALSE;
			rFrom = a8;
			rTo = d8;
		}
		if(position->castle & BLACK_KING_CASTLE){
			position->key^= castleKey[Black_King_Castle];
			position->castle &= ~BLACK_KING_CASTLE;
		}
		if(position->castle & BLACK_QUEEN_CASTLE){
			position->key^= castleKey[Black_Queen_Castle];
			position->castle &= ~BLACK_QUEEN_CASTLE;
		}
		color = Black;
		piece = Black_King;
		rook = Black_Rook;
	}
	guint64 bitMove = 1ull<<from | 1ull<<to;
	guint64 bitRook = 1ull<<rFrom | 1ull<<rTo;
	position->piece[color] ^= bitMove | bitRook;
	position->piece[piece] ^= bitMove;
	position->piece[rook] ^= bitRook;
	position->allPieces ^= bitMove | bitRook;
	position->key^=squareKey[piece][from]^squareKey[piece][to]^squareKey[rook][rFrom]^squareKey[rook][rTo];
	position->type[from] = Empty;
	position->type[to] = piece;
	position->type[rFrom] = Empty;
	position->type[rTo] = rook;
	position->pvt[Opening] += pvt[piece][to][Opening]-pvt[piece][from][Opening] +
								pvt[rook][rTo][Opening]-pvt[rook][rFrom][Opening];
	position->pvt[Endgame] += pvt[piece][to][Endgame]-pvt[piece][from][Endgame] +
								pvt[rook][rTo][Endgame]-pvt[rook][rFrom][Endgame];
	position->staticMoves = 0;
	return TRUE;
}
示例#10
0
inline void captureMoveDo(Position* position, const Move move){
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	guint piece = position->type[from];
	guint capture = position->type[to];
	guint color = piece % 2;
	guint64 bitTo = 1ull << to;
	guint64 bitMove = 1ull<<from | bitTo;
	position->piece[color] ^= bitMove;
	position->piece[piece] ^= bitMove;
	position->piece[color^1] ^= bitTo;
	position->piece[capture] ^= bitTo;
	position->allPieces ^= 1ull<<from;
	position->key ^= squareKey[piece][from] ^ squareKey[piece][to] ^ squareKey[capture][to];
	position->type[from] = Empty;
	position->type[to] = piece;
	position->pvt[Opening] += pvt[piece][to][Opening] - pvt[piece][from][Opening] - pvt[capture][to][Opening];
	position->pvt[Endgame] += pvt[piece][to][Endgame] - pvt[piece][from][Endgame] - pvt[capture][to][Endgame];
	position->material[color^1] -= pieceValue[capture];
	position->staticMoves = 0;
	position->capture = capture;
	position->phase -= piecePhase[capture];
	if(color == White){
		if(piece == White_Pawn && to >= a7) position->extend = TRUE;
		if(position->castle & WHITE_CASTLE){
			if(position->castle & WHITE_KING_CASTLE){
				if(from == e1 || from == h1){
					position->key ^= castleKey[White_King_Castle];
					position->castle &= ~WHITE_KING_CASTLE;
				}
			}
			if(position->castle & WHITE_QUEEN_CASTLE){
				if(from == e1 || from == a1){
					position->key ^= castleKey[White_Queen_Castle];
					position->castle &= ~WHITE_QUEEN_CASTLE;
				}
			}
		}
		if(position->castle & BLACK_CASTLE){
			if(position->castle & BLACK_KING_CASTLE){
				if(to == h8){
					position->key ^= castleKey[Black_King_Castle];
					position->castle &= ~BLACK_KING_CASTLE;
				}
			}
			if(position->castle & BLACK_QUEEN_CASTLE){
				if(to == a8){
					position->key ^= castleKey[Black_Queen_Castle];
					position->castle &= ~BLACK_QUEEN_CASTLE;
				}
			}
		}
	}
	else{
		if(piece == Black_Pawn && to <= h2) position->extend = TRUE;
		if(position->castle & BLACK_CASTLE){
			if(position->castle & BLACK_KING_CASTLE){
				if(from == e8 || from == h8){
					position->key ^= castleKey[Black_King_Castle];
					position->castle &= ~BLACK_KING_CASTLE;
				}
			}
			if(position->castle & BLACK_QUEEN_CASTLE){
				if(from == e8 || from == a8){
					position->key ^= castleKey[Black_Queen_Castle];
					position->castle &= ~BLACK_QUEEN_CASTLE;
				}
			}
		}
		if(position->castle & WHITE_CASTLE){
			if(position->castle & WHITE_KING_CASTLE){
				if(to == h1){
					position->key ^= castleKey[White_King_Castle];
					position->castle &= ~WHITE_KING_CASTLE;
				}
			}
			if(position->castle & WHITE_QUEEN_CASTLE){
				if(to == a1){
					position->key ^= castleKey[White_Queen_Castle];
					position->castle &= ~WHITE_QUEEN_CASTLE;
				}
			}
		}
	}
}
示例#11
0
inline void normalMoveDo(Position* position, const Move move){
	guint from = moveGetFrom(move);
	guint to = moveGetTo(move);
	guint piece = position->type[from];
	guint color = piece % 2;
	guint64 bitMove = 1ull << from | 1ull << to;
	position->piece[color] ^= bitMove;
	position->piece[piece] ^= bitMove;
	position->allPieces ^= bitMove;
	position->key ^= squareKey[piece][from] ^ squareKey[piece][to];
	position->type[from] = Empty;
	position->type[to] = piece;
	position->pvt[Opening] += pvt[piece][to][Opening] - pvt[piece][from][Opening];
	position->pvt[Endgame] += pvt[piece][to][Endgame] - pvt[piece][from][Endgame];
	if(color == White){
		if(piece == White_Pawn){
			position->staticMoves = 0;
			if(to - from == 16 && (position->piece[Black_Pawn] & ((1ull<<(to+1)) | (1ull<<(to-1))))){
				position->enPassant = to - 8;
				position->key ^= enPassantKey[file(position->enPassant)];
			}
			if(to >= a7) position->extend = TRUE;
		}
		if(position->castle & WHITE_CASTLE){
			if(position->castle & WHITE_KING_CASTLE){
				if(from == e1 || from == h1){
					position->key ^= castleKey[White_King_Castle];
					position->castle &= ~WHITE_KING_CASTLE;
				}
			}
			if(position->castle & WHITE_QUEEN_CASTLE){
				if(from == e1 || from == a1){
					position->key ^= castleKey[White_Queen_Castle];
					position->castle &= ~WHITE_QUEEN_CASTLE;
				}
			}
		}
	}
	else{
		if(piece == Black_Pawn){
			position->staticMoves = 0;
			if(from - to == 16 && (position->piece[White_Pawn] & ((1ull<<(to+1)) | (1ull<<(to-1))))){
				position->enPassant = to + 8;
				position->key ^= enPassantKey[file(position->enPassant)];
			}
			if(to <= h2) position->extend = TRUE;
		}
		if(position->castle & BLACK_CASTLE){
			if(position->castle & BLACK_KING_CASTLE){
				if(from == e8 || from == h8){
					position->key ^= castleKey[Black_King_Castle];
					position->castle &= ~BLACK_KING_CASTLE;
				}
			}
			if(position->castle & BLACK_QUEEN_CASTLE){
				if(from == e8 || from == a8){
					position->key ^= castleKey[Black_Queen_Castle];
					position->castle &= ~BLACK_QUEEN_CASTLE;
				}
			}
		}
	}
}
示例#12
0
gboolean moveDo(Position* position, const Move move){
	History* history = &position->history[position->ply];
	history->move = move;
	history->key = position->key;
	history->capture = position->capture;
	history->staticMoves = position->staticMoves;
	history->enPassant = position->enPassant;
	history->castle = position->castle;
	history->inCheck = position->inCheck;
	history->material[White] = position->material[White];
	history->material[Black] = position->material[Black];
	history->pvt[Opening] = position->pvt[Opening];
	history->pvt[Endgame] = position->pvt[Endgame];
	history->extend = position->extend;
	history->phase = position->phase;

	#ifndef G_DISABLE_ASSERT 
	if(move != Null_Move && position->type[moveGetFrom(move)]%2 != position->turn){
		positionPrint(position);
		g_printf("Wrong move (");
		movePrint(move);
		g_printf(")\n");
		g_error("!!\n");
	}
	#endif
	if(position->enPassant != 0){
		position->key ^= enPassantKey[file(position->enPassant)];
		position->enPassant = 0;
	}
	position->capture = Empty;
	position->extend = FALSE;
	position->staticMoves ++;

	switch(moveGetType(move)){
		case Normal: 	{ normalMoveDo(position, move); break;}
		case Capture:	{ captureMoveDo(position, move); break;}
		case En_Passant:{ enPassantMoveDo(position, move); break;}
		case Castle:	{
			if(!castleMoveDo(position,move)){
				position->enPassant = history->enPassant;
				position->capture = history->capture;
				position->extend = history->extend;
				position->staticMoves--;
				#ifndef G_DISABLE_ASSERT 
				positionIsOk(position);
				#endif
				return FALSE;
			}else{
				position->turn ^= 1; 
				position->key ^= turnKey;
				position->ply++;
				position->inCheck = positionIsInCheck(position); /* Speed up (rook only)*/
				if(position->inCheck) position->extend = TRUE;
				#ifndef G_DISABLE_ASSERT 
				positionIsOk(position);
				#endif
				return TRUE;
			}
		}
		case Promote_Queen:	{ promoteMoveDo(position,move,Queen); break;}
		case Promote_Rook: 	{ promoteMoveDo(position,move,Rook); break;}
		case Promote_Bishop:	{ promoteMoveDo(position,move,Bishop); break;}
		case Promote_Knight:	{ promoteMoveDo(position,move,Knight); break;}
		case Null_Move:	{
			position->turn ^= 1; 
			position->key ^= turnKey;
			position->ply++;
			position->staticMoves = 0;
			#ifndef G_DISABLE_ASSERT 
			positionIsOk(position);
			#endif
			return TRUE;
		}
		default: { g_error("Wrong move type!\n"); }
	};
	position->turn ^= 1; 
	position->key ^= turnKey;
	position->ply++;
	if(!positionGood(position)){
		moveUndo(position);
		return FALSE;
	}
	position->inCheck = positionIsInCheck(position); /* Speed up */
	if(position->inCheck) position->extend = TRUE;
	#ifndef G_DISABLE_ASSERT 
	positionIsOk(position);
	#endif
	return TRUE;
}