4
\$\begingroup\$

I'm currently in the process of building my own Chess game engine and could really use some suggestions on how to make this segment of code for calculating diagonal moves more efficient. (This is obviously only for diagonals going Up-Right.)

As of now I'm using "Try-Except" to iterate by 1, and then my return statement filters out any off-board values. However this seems like a very bulky way of doing things.

import argparse, json

chessBoard = [[1, 1, 1, 1, 1, 1, 1, 1] for i in range(8)]

chess_map_from_alpha_to_index = {
    "a" : 0,
    "b" : 1,
    "c" : 2,
    "d" : 3,
    "e" : 4,
    "f" : 5,
    "g" : 6,
    "h" : 7
}

chess_map_from_index_to_alpha = {
    0: "a",
    1: "b",
    2: "c",
    3: "d",
    4: "e",
    5: "f",
    6: "g",
    7: "h"
}


def getBishopMoves(pos, chessBoard):
    column, row = list(pos.strip().lower())
    row = int(row) - 1
    column = chess_map_from_alpha_to_index[column]
    i,j = row, column
    solutionMoves = []

#Up-Right Diagonal
    try:
        temp = chessBoard[i + 1][j + 1]
        solutionMoves.append([i + 1, j + 1])
    except:
        pass
    try:
        temp = chessBoard[i + 2][j + 2]
        solutionMoves.append([i + 2, j + 2])
    except:
        pass
    try:
        temp = chessBoard[i + 3][j + 3]
        solutionMoves.append([i + 3, j + 3])
    except:
        pass
    try:
        temp = chessBoard[i + 4][j + 4]
        solutionMoves.append([i + 4, j + 4])
    except:
        pass
    try:
        temp = chessBoard[i + 5][j + 5]
        solutionMoves.append([i + 5, j + 5])
    except:
        pass
    try:
        temp = chessBoard[i + 6][j + 6]
        solutionMoves.append([i + 6, j + 6])
    except:
        pass
    try:
        temp = chessBoard[i + 7][j + 7]
        solutionMoves.append([i + 7, j + 7])
    except:
        pass    
    try:
        temp = chessBoard[i + 7][j + 7]
        solutionMoves.append([i + 7, j + 7])
    except:
        pass   

    temp = [i for i in solutionMoves if i[0] >=0 and i[1] >=0]
    solutionMoves = ["".join([chess_map_from_index_to_alpha[i[1]], str(i[0] + 1)]) for i in temp]
    solutionMoves.sort()
    return solutionMoves
\$\endgroup\$
  • 2
    \$\begingroup\$ Can you give an example of a call to getBishopMoves()? \$\endgroup\$ – Daniel Jun 24 '18 at 7:43
  • \$\begingroup\$ There's some JSON code I left out but the call is essentially moveEngine.py -p "bishop" -l "a1" \$\endgroup\$ – Kevin Hebert Jun 24 '18 at 14:36
  • \$\begingroup\$ Sorry, but that's not really helpful, since we don't know how those arguments are parsed. Can you add an actual example of input / output when calling getBishopMoves()? \$\endgroup\$ – Daniel Jun 24 '18 at 16:55
4
\$\begingroup\$

Go through the PEP-8 style guide. You have inconsistent naming convention. A mixed case of camelCase and snake_case throws off the developer. Follow snake_case for variables and camelCase for class etc.

The first thing that comes to mind is a loop:

for pos in range(1, 8):
    try:
        temp = chessBoard[i + pos][j + pos]
        solutionMoves.append([i + pos, j + pos])
    except:
        break

which about covers the whole of your try-except blocks.


However, with chess; I'd suggest using coordinate system to move around the board.

Design a class Point which takes \$ (x, y) \$ position and define the __add__, __sub__, __neg__ etc. as follows (rough, modify as per your needs):

class Point(tuple):
    def __add__(self, other):
        return Point(v + w for v, w in zip(self, other))

    def __radd__(self, other):
        return Point(w + v for v, w in zip(self, other))

    def __sub__(self, other):
        return Point(v - w for v, w in zip(self, other))

    def __neg__(self):
        return -1 * self

    def __mul__(self, s):
        return Vector(v * s for v in self)

    def __rmul__(self, s):
        return Vector(v * s for v in self)

Now, define your movement direction as a point vector:

DIR_TOP_RIGHT = Point(1, 1)

when you want to move inside the board, just add a multiple of direction to the current point:

current = Point(i, j)
new = current + (distance * DIR_TOP_RIGHT)

Next, define a method (inside a class ChessBoard which checks whether a point lies inside the board or not. This should be quite easy. This ChessBoard class should also be the one responsible for converting your Point object from \$ (1, 1) \$ format to B1 etc.

\$\endgroup\$
  • \$\begingroup\$ I really appreciate the detailed response mate, though, I have to say a lot of that went over my head. Are there any articles you could suggest for me to get a better grasp on what you were saying? Mostly confused about what add, sub, neg, are supposed to represent. Also not really sure how the user would choose his "multiple of direction" through a GUI \$\endgroup\$ – Kevin Hebert Jun 24 '18 at 14:38
  • 2
    \$\begingroup\$ @Kevin Hebert __add__(), __sub__(), and __neg__() are examples of magic methods. Essentially they allow you to operate on two instances of Point using common operators, like + corresponding to __add__(), - corresponding to __sub__(), etc. See also 'Data model: Special method names: basic customization' \$\endgroup\$ – Daniel Jun 24 '18 at 16:53
  • \$\begingroup\$ Thx for the link; diving in now. Do you have any books you recommend? I'm feeling very overwhelmed already as I'm eventually trying to make this an online, multiplayer game... \$\endgroup\$ – Kevin Hebert Jun 24 '18 at 17:14
  • 1
    \$\begingroup\$ @KevinHebert I don't know of any books specifically about magic methods, and I'm hesitant to recommend any books because I don't know your skill level. If you have trouble understanding classes, the Python tutorial page on classes may be a useful resource. If you just want an awesome and complete introductory course to Python, check out Learn Python the Hard Way. Apart from that, a search for 'Python classes' will get you pretty far. \$\endgroup\$ – Daniel Jun 26 '18 at 8:43
  • \$\begingroup\$ Completely get that. I'll check out the link as my knowledge on classes is definitely a little fuzzy. As for my skill level, I would say it's rather minimal. I've done quite a few tutorials on Python / Django + front end development, along with taking a university class on C++. However, I really struggle in trying to piece together all my knowledge. That's part of the reason why I'm trying to build this chess engine (and eventually online/multiplayer chess game). I understand it's quite an undertaking but I think doing a real project like this is the only way I'll actually learn \$\endgroup\$ – Kevin Hebert Jun 26 '18 at 21:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.