/*
    STB Generator
    Copyright (C) 2006 Gian-Carlo Pascutto
   
    File: recurse.c
    Purpose: main generation recursion
*/

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#include "global.h"
#include "utils.h"
#include "board.h"
#include "sfile.h"
#include "iterate.h"

int valid_matsig(matsig_s *s) {
    int i;    
    int wpawns, bpawns;    
    int wmat, bmat;
    
    wpawns = 0;
    bpawns = 0;
    
    for (i = 0; i < s->npieces[wpawn]; i++) {
        wpawns += 1 << (3 * (s->pawnrank[WHITE][i] - 2));
    }
        
    for (i = 0; i < s->npieces[bpawn]; i++) {
        bpawns += 1 << (3 * (s->pawnrank[BLACK][i] - 2));
    }                    
    
    wmat =   (s->npieces[wqueen]  << (3 * 9))
           + (s->npieces[wrook]   << (3 * 8))
           + (s->npieces[wbishop] << (3 * 7))
           + (s->npieces[wknight] << (3 * 6))
           + wpawns;
    
    bmat =   (s->npieces[bqueen]  << (3 * 9))
           + (s->npieces[brook]   << (3 * 8))
           + (s->npieces[bbishop] << (3 * 7))
           + (s->npieces[bknight] << (3 * 6))
           + bpawns;
           
    assert(wmat >= 0 && bmat >= 0);           
           
    return (wmat >= bmat);
}

INDEX recurse_gen(matsig_s *s) {
    int j, inc, pcnt;  
    matsig_s news;
    sfile_s *sf;    
    INDEX sizes;    

    printf("recurse_gen: ");
    print_sig(s);
    printf("\n");        
    
    /*
        are we a valid material config?
    */
    if (!valid_matsig(s)) {     
        return 0;
    }
    
    /*
        are we made already?
    */
    sf = sf_open(s);

    if (sf != NULL) {
        sf_close(sf);
        return 0;
    }
    
    sizes = 0;

    /*
        check all direct subgames
    */
    memcpy(&news, s, sizeof(matsig_s));

    for (j = 0; j < 5; j++) {
        for (inc = 0; inc < 2; inc++) {
            if (news.npieces[wpcs[j] + inc] > 0) {
                news.npieces[wpcs[j] + inc]--;        
                sizes += recurse_gen(&news);
                news.npieces[wpcs[j] + inc]++;        
            }       
        }
    }

    /*
        if there are pawns, do promotions and moves upwards
    */
    for (inc = 0; inc < 2; inc++) {
        if (news.npieces[wpawn + inc] > 0) {
            /*
                replace pawn by promoted piece and try
                
            */
            news.npieces[wpawn + inc]--;
            for (j = 0; j < 4; j++) {
                news.npieces[wpcs[j] + inc]++;
                sizes += recurse_gen(&news);
                news.npieces[wpcs[j] + inc]--;
            }            
            news.npieces[wpawn + inc]++;
            
            /*
                replace pawn by advanced pawn
            */
            pcnt = news.npieces[wpawn + inc];
            
            j = 0;
            while (j < pcnt && news.pawnrank[inc][j] == 7 ) {
                j++;
            }                        
            if (j < pcnt) {
                news.pawnrank[inc][j]++;
                sizes += recurse_gen(&news);
                news.pawnrank[inc][j]--;                               
            }            
        }
    }            

    /*
        ok, we don't exist, our children are ready,
        we're good to go
    */
    sf = sf_create(s);

    sizes += gen(sf, s);

    sf_close(sf);    
    
    return sizes;
}
