5
\$\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
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jun 24, 2018 at 6:45
\$\endgroup\$
3
  • 2
    \$\begingroup\$ Can you give an example of a call to getBishopMoves()? \$\endgroup\$ Commented Jun 24, 2018 at 7:43
  • \$\begingroup\$ There's some JSON code I left out but the call is essentially moveEngine.py -p "bishop" -l "a1" \$\endgroup\$ Commented Jun 24, 2018 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\$ Commented Jun 24, 2018 at 16:55

2 Answers 2

5
\$\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.

answered Jun 24, 2018 at 10:30
\$\endgroup\$
5
  • \$\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\$ Commented Jun 24, 2018 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\$ Commented Jun 24, 2018 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\$ Commented Jun 24, 2018 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\$ Commented Jun 26, 2018 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\$ Commented Jun 26, 2018 at 21:01
1
\$\begingroup\$

Computing moves seems like something that will happen a lot in a chess game :-).

That being said, why don't you write a function that will generate a list of all the possible moves for a piece from a given position and store them in a loadable format?

I just recently saw someone else ask a chess question mentioning something called bitboard, so I know there's at least two standards for board positions. You can either use UCI notation ("a2") or bitboard notation (0x100).

However you choose to represent them, simply perform the computations to generate all possible moves for a given piece in a given position, possibly including some special moves as either a separate move lookup or as a separate piece lookup (for example, "king-n" for no castle yet and "king-y" for castled already).

Then you can just look up "raw" moves from a dictionary:

possible_moves = raw_moves['bishop'][position]

Subsequently, you would have to look for blocking pieces and filter them out. Depending on your storage implementation, this again seems like something you could precompute.

A lot of this suggestion is "trading space for time". That is, I'm suggesting you create a LOT of stored data that you could use in order to avoid doing computations at run-time. It would slow down the loading of your program, but should speed up the turn-by-turn execution.

If you choose to use UCI format for positions, you will want to look at Python's set and frozenset built-in types.

If you choose to go with bitboard, you can use bitwise operations on integer values, which Python supports directly.

answered Aug 9, 2020 at 19:35
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.