src/rules/knight.c

Fri, 28 Mar 2014 14:32:52 +0100

author
Mike Becker <universe@uap-core.de>
date
Fri, 28 Mar 2014 14:32:52 +0100
changeset 16
a298c6637c30
parent 12
84880c7e1ea6
permissions
-rw-r--r--

introduced status codes for get_location to produce detailed error messages + added knight rules

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2014 Mike Becker. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "knight.h"
#include "rules.h"
#include <math.h>

_Bool knight_chkrules(Move *move) {
    int dx = abs(move->fromfile - move->tofile);
    int dy = abs(move->fromrow - move->torow);
    
    return (dx == 2 && dy == 1) || (dx == 1 && dy == 2);
}

static int knight_getloc_fixedrow(Board board, Move *move) {
    int d = 3 - abs(move->fromrow - move->torow);
    
    if (d == 1 || d == 2) {
        if (move->tofile < 6 &&
            board[move->fromrow][move->tofile + d] == move->piece) {
            if (move->fromfile == POS_UNSPECIFIED) {
                move->fromfile = move->tofile + d;
                return VALID_MOVE_SYNTAX;
            } else {
                return AMBIGUOUS_MOVE;
            }
        }
        if (move->tofile > 1 &&
            board[move->fromrow][move->tofile - d] == move->piece) {
            if (move->fromfile == POS_UNSPECIFIED) {
                move->fromfile = move->tofile - d;
                return VALID_MOVE_SYNTAX;
            } else {
                return AMBIGUOUS_MOVE;
            }
        }
    }
    
    return INVALID_POSITION;
}

static int knight_getloc_fixedfile(Board board, Move *move) {
    int d = 3 - abs(move->fromfile - move->tofile);
    
    if (d == 1 || d == 2) {
        if (move->torow < 6 &&
            board[move->torow + d][move->fromfile] == move->piece) {
            if (move->fromrow == POS_UNSPECIFIED) {
                move->fromrow = move->torow + d;
                return VALID_MOVE_SYNTAX;
            } else {
                return AMBIGUOUS_MOVE;
            }
        }
        if (move->torow > 1 &&
            board[move->torow - d][move->fromfile] == move->piece) {
            if (move->fromrow == POS_UNSPECIFIED) {
                move->fromrow = move->torow - d;
                return VALID_MOVE_SYNTAX;
            } else {
                return AMBIGUOUS_MOVE;
            }
        }
    }
    
    return INVALID_POSITION;
}

int knight_getlocation(Board board, Move *move) {
    
    if (move->fromfile != POS_UNSPECIFIED) {
        return knight_getloc_fixedfile(board, move);
    }
    
    if (move->fromrow != POS_UNSPECIFIED) {
        return knight_getloc_fixedrow(board, move);
    }
    
    for (int x = -2 ; x <= 2 ; x++) {
        if (x == 0) {
            continue;
        }
        for (int y = -2 ; y <= 2 ; y++) {
            if (y == 0 || y == x) {
                continue;
            }
            uint8_t cx = move->tofile + x;
            uint8_t cy = move->torow + y;

            if (isidx(cx) && isidx(cy) && board[cy][cx] == move->piece) {
                if (move->fromfile == POS_UNSPECIFIED
                    && move->fromrow == POS_UNSPECIFIED) {
                    move->fromfile = cx;
                    move->fromrow = cy;
                } else {
                    return AMBIGUOUS_MOVE;
                }
            }
        }
    }
    
    if (move->fromfile == POS_UNSPECIFIED || move->fromrow == POS_UNSPECIFIED) {
        return INVALID_POSITION;
    } else {
        return VALID_MOVE_SYNTAX;
    }
}

mercurial