示例#1
0
 /// <summary>
 /// Avalia a Dama.
 /// </summary>
 /// <remarks>
 /// Mobilidade e ataques a casas perto ao rei pode ser addicionada.
 /// </remarks>
 /// <param name="pontuacao">Pontuação do lado branco ou preto</param>
 /// <param name="indice">Índice da casa da dama</param>
 private void AvaliaDama(Pontuacao pontuacao, int indice)
 {
     Fase -= Pontuacao.Fase.DAMA;
     pontuacao.Inicial += Pontuacao.Material.DAMA_INICIO;
     pontuacao.Final   += Pontuacao.Material.DAMA_FINAL;
     pontuacao.Final   += Pontuacao.Tabela.CENTRALIZACAO[Defs.Converte12x12Para8x8(indice)] / 2;
 }
示例#2
0
 /// <summary>
 /// Avalia o bispo.
 /// </summary>
 /// <remarks>
 /// Vai tentar centralizar o bispo.
 /// Outro item que pode ser adicionado é uma relação com os próprios peões,
 /// não estando no quadrado da mesma cor do bispo.
 /// </remarks>
 /// <param name="pontuacao">Pontuação do lado branco ou preto</param>
 /// <param name="indice">Índice da casa do bispo</param>
 private void AvaliaBispo(Pontuacao pontuacao, int indice)
 {
     Fase -= Pontuacao.Fase.BISPO;
     pontuacao.Inicial += Pontuacao.Material.BISPO_INICIO;
     pontuacao.Inicial += Pontuacao.Tabela.CENTRALIZACAO[Defs.Converte12x12Para8x8(indice)];
     pontuacao.Final   += Pontuacao.Material.BISPO_FINAL;
     pontuacao.Final   += Pontuacao.Tabela.CENTRALIZACAO[Defs.Converte12x12Para8x8(indice)];
 }
示例#3
0
 /// <summary>
 /// Avalia o Rei.
 /// </summary>
 /// <remarks>
 /// Apenas dá um bônus para peões na frente do rei, ou seja, escudo de peão (pawn shield).
 /// O que pode ser adicionado é uma penalidade para muitos peões inimigos perto do rei, o que
 /// significa que um ataque de peão está se formando.
 /// Especialmente em termos de segurança do rei, se as peças inimigas estão atacando a área próxima ao rei,
 /// pode ser um grande valor a este item. Em geral a segurança do rei é difícil de calibrar corretamente e
 /// requer muitos testes.
 /// Além disso, algo a considerar é a presença da dama inimiga ao avaliar a segurança do rei. Sem a dama o
 /// valor da segurança do rei reduz drasticamente.
 /// </remarks>
 /// <param name="pontuacao">Pontuação do lado branco ou preto</param>
 /// <param name="indice">Índice da casa do rei</param>
 /// <param name="dados_rei">Informação relativa à cor a ser avaliada.</param>
 private void AvaliaRei(Pontuacao pontuacao, int indice, DadosRei dados_rei)
 {
     for (int i = 0; i < dados_rei.DirecaoEmFrente.Length; i++)
     {
         if (Tabuleiro.ObtemPeca(indice + i) == dados_rei.PeaoAmigo)
         {
             pontuacao.Inicial += Pontuacao.Rei.PEAO_ESCUDO;
         }
     }
     pontuacao.Inicial += dados_rei.TabelaInicio[Defs.Converte12x12Para8x8(indice)];
 }
示例#4
0
        /// <summary>
        /// Gera uma string FEN representando a posição atual no tabuleiro .
        /// </summary>
        /// <param name="tabuleiro">tabuleiro com a posição para gerar a string FEN</param>
        /// <returns>string FEN</returns>
        public static string ConverteTabuleiroParaFEN(Tabuleiro tabuleiro)
        {
            string fen = "";

            fen += FEN.ObtemDescPosicao(tabuleiro);
            fen += " " + tabuleiro.CorJogar.ParaTexto();
            fen += " " + FEN.ObtemDescRoque(tabuleiro);
            fen += " " + Defs.ObtemDescCasa(tabuleiro.IndiceEnPassant);
            fen += " " + tabuleiro.ContadorRegra50.ToString();
            fen += " " + tabuleiro.ContadorMovimentos.ToString();

            return(fen);
        }
示例#5
0
 /// <summary>
 /// Avalia peões pretos.
 /// </summary>
 /// <see cref="AvaliaPeaoBranco(int)"/>
 /// <param name="indice">Índice da casa do peão</param>
 private void AvaliaPeaoPreto(int indice)
 {
     Fase          -= Pontuacao.Fase.PEAO;
     Preto.Inicial += Pontuacao.Material.PEAO_INICIO;
     Preto.Inicial += Pontuacao.Tabela.PEAO_PRETO[Defs.Converte12x12Para8x8(indice)];
     if (indice == (int)Defs.INDICE.D5 || indice == (int)Defs.INDICE.E5)
     {
         Preto.Inicial += Pontuacao.Peao.PEAO_CENTRAL_1;
     }
     if (indice == (int)Defs.INDICE.D6 || indice == (int)Defs.INDICE.E6)
     {
         Preto.Inicial += Pontuacao.Peao.PEAO_CENTRAL_2;
     }
     Preto.Final += Pontuacao.Material.PEAO_FINAL;
     Preto.Final += Pontuacao.Tabela.PEAO_PRETO[Defs.Converte12x12Para8x8(indice)];
 }
示例#6
0
 /// <summary>
 /// Avalia peões brancos.
 /// </summary>
 /// <remarks>
 /// Valor material, valor na casa de acordo com uma tabela e bônus de centralização.
 /// Outros termos que podems ser adicionados:
 /// Peões passados: bônus para peões que não podem ser capturados por peões inimigos.
 /// Peões isolados: penalidade para peões sem peões amigos em colunas vizinhas.
 /// Peões conectados: bônus para peões que se apoiam.
 /// Peões duplicados: penalidade para peões na mesma coluna.
 /// Peões para trás: penalidade para peões que não podem avançar sem encontrar os peões inimigos.
 /// Peões candidatos: bônus para peões que podem se tornar passados.
 /// Outra idéia é armazenar o valor da estrutura de peões em uma tabela, e quando encontramos
 /// a mesma estrutura de peões mais tarde, podemos usar o valor calculado dessa tabela. Isso ajuda
 /// o desempenho, pois a estrutura do peão pode repetir muito em uma pesquisa.
 /// Neste caso, podemos usar uma chave zobrist para a estrutura do peão. Normalmente, isso é
 /// chamado de "pawn hash table".
 /// </remarks>
 /// <param name="indice">Índice da casa do peão</param>
 private void AvaliaPeaoBranco(int indice)
 {
     Fase           -= Pontuacao.Fase.PEAO;
     Branco.Inicial += Pontuacao.Material.PEAO_INICIO;
     Branco.Inicial += Pontuacao.Tabela.PEAO_BRANCO[Defs.Converte12x12Para8x8(indice)];
     if (indice == (int)Defs.INDICE.D4 || indice == (int)Defs.INDICE.E4)
     {
         Branco.Inicial += Pontuacao.Peao.PEAO_CENTRAL_1;
     }
     if (indice == (int)Defs.INDICE.D3 || indice == (int)Defs.INDICE.E3)
     {
         Branco.Inicial += Pontuacao.Peao.PEAO_CENTRAL_2;
     }
     Branco.Final += Pontuacao.Material.PEAO_FINAL;
     Branco.Final += Pontuacao.Tabela.PEAO_BRANCO[Defs.Converte12x12Para8x8(indice)];
 }
示例#7
0
        /// <summary>
        /// Retorna a lista ordenada de movimentos.
        /// </summary>
        /// <remarks>
        /// Ordem de classificação:
        /// 1. Movimento melhor vindo da tabela de transposição.
        /// 2. Capturas
        /// 3. Movimentos simples classificados pela tabela de valores.
        ///
        /// Falta aqui os movimentos matadores (killer moves). Quase todos os programas de xadrez
        /// usam esta técnica. Eu me pergunto se alguém poderia fazer isso e se faria o Enxadrista
        /// um pouco melhor.
        /// </remarks>
        /// <param name="cor">Cor do lado com movimentos a ordenar.</param>
        /// <param name="lista">List de movimentos.</param>
        /// <param name="melhor">Melhor movimento que será ordenado primeiro, normalmente da tabela de transposição</param>
        /// <returns>Lista ordenada de movimentos.</returns>
        public List <Movimento> Orderna(Cor cor, List <Movimento> lista, Movimento melhor)
        {
            foreach (var movimento in lista)
            {
                if (movimento.Equals(melhor))
                {
                    movimento.ValorOrdenacao = 100000000;
                    continue;
                }
                if (movimento.Captura())
                {
                    movimento.ValorOrdenacao = ValorCaptura(movimento) * 10000;
                    continue;
                }
                int indice_peca = IndicePeca(movimento.Peca);
                int indice_casa = Defs.Converte12x12Para8x8(movimento.IndiceDestino);
                movimento.ValorOrdenacao = Tabela[indice_peca][indice_casa];
            }

            return(lista.OrderByDescending(m => m.ValorOrdenacao).ToList());
        }
示例#8
0
        /// <summary>
        /// Atualiza informação sempre que um bom movimento é encontrada.
        /// </summary>
        /// <remarks>
        /// Note que consideramos somente os movimentos simples. Captura já possui
        /// um valor maior do que movimentos simples.
        /// </remarks>
        /// <param name="cor">Cor do lado fazendo o movimento.</param>
        /// <param name="movimento">Movimento considerado bom.</param>
        /// <param name="profundidade">Profundidade que o movimento foi pesquisado.</param>
        public void AtualizaHistoria(Cor cor, Movimento movimento, int profundidade)
        {
            if (movimento.Tatico())
            {
                return;
            }

            int indice_peca = IndicePeca(movimento.Peca);
            int indice_casa = Defs.Converte12x12Para8x8(movimento.IndiceDestino);

            Tabela[indice_peca][indice_casa] += profundidade;

            // Se o valor na tabela estiver muito alto, é feito um ajuste a todos valores.
            if (Tabela[indice_peca][indice_casa] > 9000)
            {
                for (int peca = 0; peca < NUMERO_PECAS; peca++)
                {
                    for (int casa = 0; casa < NUMERO_CASAS; casa++)
                    {
                        Tabela[peca][casa] /= 8;
                    }
                }
            }
        }
示例#9
0
        /// <summary>
        /// Converte uma string FEN para o tabuleiro.
        /// </summary>
        /// <param name="fen">string FEN representando uma posicão</param>
        /// <param name="tabuleiro">tabuleiro a ser atualizado com a posicão FEN</param>
        public static void ConverteFenParaTabuleiro(string fen, Tabuleiro tabuleiro)
        {
            string[] partes = fen.Split(' ');

            string posicao_pecas       = partes[0];
            string cor_jogar           = partes[1];
            string estado_roque        = partes[2];
            string casa_en_passant     = partes[3];
            string contador_regra_50   = partes.Length > 4 ? partes[4] : "0";
            string contador_movimentos = partes.Length > 4 ? partes[5] : "0";

            int fileira = Defs.PRIMEIRA_FILEIRA;
            int coluna  = Defs.PRIMEIRA_COLUNA;

            foreach (var caracter in posicao_pecas)
            {
                if (char.IsDigit(caracter))
                {
                    coluna += int.Parse(caracter.ToString());
                }
                else
                {
                    switch (caracter)
                    {
                    case '/':
                        fileira += 1;
                        coluna   = Defs.PRIMEIRA_COLUNA;
                        break;

                    default:
                        tabuleiro.ColocaPeca(fileira * Defs.NUMERO_COLUNAS + coluna++, caracter.ParaPeca());
                        break;
                    }
                }
            }

            tabuleiro.CorJogar = cor_jogar.ParaCor();

            if (estado_roque.Contains('K'))
            {
                tabuleiro.RoqueE1G1 = true;
            }
            if (estado_roque.Contains('Q'))
            {
                tabuleiro.RoqueE1C1 = true;
            }
            if (estado_roque.Contains('k'))
            {
                tabuleiro.RoqueE8G8 = true;
            }
            if (estado_roque.Contains('q'))
            {
                tabuleiro.RoqueE8C8 = true;
            }

            tabuleiro.IndiceEnPassant = Defs.ObtemIndiceDaPosicao(casa_en_passant);

            tabuleiro.ContadorRegra50 = int.Parse(contador_regra_50);

            tabuleiro.ContadorMovimentos = int.Parse(contador_movimentos);
        }