Skip to content
Snippets Groups Projects
Select Git revision
  • f63ac8afd8110d3fcea9dd1f7eb2b8175f4ac306
  • master default
  • glibc-cacheline-exclusive
  • cmd_wrapper
  • bumpptrs
  • wait4_rusage
  • cache_exclusive_alloc
  • loop_keep_allocs
8 results

util.py

Blame
  • openings.c 2.94 KiB
    /*
     * This file is part of the SPiC Project SPiChess  (https://gitlab.cs.fau.de/i4/spic/chess).
     * Copyright (c) 2017 - 2020 by Bernhard Heinloth
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation, version 3.
     *
     * This program is distributed in the hope that it will be useful, but
     * WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     * General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program. If not, see <http://www.gnu.org/licenses/>.
     */
    
    #include <stdlib.h>
    #include <avr/pgmspace.h>
    
    #include "openings.h"
    #include "openings_helper.h"
    
    #include "chess.h"
    #include "board.h"
    
    #include "openings.db"
    
    #define COUNT(X) (sizeof(X)/sizeof(X[0]))
    
    _Static_assert(COUNT(openings) < OPENING_NONE, "Too much opening moves, cannot handle them");
    _Static_assert(RAND_MAX > OPENINGS_GOOD, "Maximum random number is smaller than the possible openings");
    
    static uint8_t opening_invalid[COUNT(openings) / 8 + 1];
    
    void openings_reset() {
    	for (uint8_t o = 0; o < COUNT(opening_invalid); o++)
    		opening_invalid[o] = 0;
    }
    
    static uint8_t openings_invalidate(uint16_t moveCounter) {
    	uint8_t use_opening = OPENING_NONE;
    	for (uint8_t o = 0; o < COUNT(openings); o++)
    		if (OPENING_IS_VALID(o)){
    			if (OPENING_FROM_X(o, moveCounter) == selected.fromX && OPENING_FROM_Y(o, moveCounter) == selected.fromY && OPENING_TO_X(o, moveCounter) == selected.toX && OPENING_TO_Y(o, moveCounter) == selected.toY) {
    				if (use_opening == OPENING_NONE)
    					use_opening = o;
    			} else
    				OPENING_INVALIDATE(o);
    		}
    	return use_opening;
    }
    
    bool openings_move(int8_t player) {
    	uint8_t use_opening = OPENING_NONE;
    	uint16_t moveCounter = board_moveCounter();
    	if (moveCounter < OPENING_ROUNDS * 2) {
    		use_opening = moveCounter > 0 ? openings_invalidate(moveCounter) : (rand() % OPENINGS_GOOD);
    	}
    	if (use_opening != OPENING_NONE) {
    		selected = (chess_move) {
    						.fromX = OPENING_FROM_X(use_opening, moveCounter + 1),
    						.fromY = OPENING_FROM_Y(use_opening, moveCounter + 1),
    						.toX = OPENING_TO_X(use_opening, moveCounter + 1),
    						.toY = OPENING_TO_Y(use_opening, moveCounter + 1)
    					};
    		if (!board_canMove(selected.fromY, selected.fromX, selected.toY, selected.toX, player))
    			error(use_opening);
    		else
    			openings_invalidate(moveCounter + 1);
    		return true;
    	} else
    		return false;
    }
    
    
    #ifndef NDEBUG
    void openings_validate() {
    	for (uint8_t o = 0; o < COUNT(openings); o++) {
    		board_reset();
    		int8_t player = -1;
    		for (uint8_t m = 1; m <= OPENING_ROUNDS * 2; m++) {
    			player *= -1;
    			selected = (chess_move) {
    							.fromX=OPENING_FROM_X(o, m),
    							.fromY = OPENING_FROM_Y(o, m),
    							.toX = OPENING_TO_X(o, m),
    							.toY = OPENING_TO_Y(o, m)
    						};
    			if (!board_move(player) )
    				error(o);
    		}
    	}
    }
    #endif