Page 1 of 2

Chess board array

Posted: Fri Nov 20, 2015 1:56 am
by KWingfoot
I am rather new to programming and Python. I have a project I thought I would try to use my pyboard to learn with. It's essentially based off of the work of Bergers who uses a Teensy 2.0 to read a chess board using magnets and reed switches. I have a board (a Mephisto Modular) that works with the Teensy program, so I know the board is good. When I try to use his programming idea - https://sites.google.com/site/bergerspr ... rogramming I run into a problem. The problem is, I always get an entire column turning to 0 instead of just the correct row/column. Below is the code I put together for it so far. I'm sure there are many ways it can be optimized, but again, being new to programming I'm making things work.

Code: Select all

from pyb import Pin

cletters = ['Y1', 'Y2', 'Y3', 'Y4', 'Y5', 'Y6', 'Y7', 'Y8']
rnumbers = ['X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X7', 'X8']

board = [[0 for j in range(8)] for i in range(8)]

rcount = 0
ccount = 0

for number in rnumbers:
	Pin(number, Pin.OUT_PP)
	Pin(number).high

for letter in cletters:
	Pin(letter, Pin.OUT_PP)
	Pin(letter).low

for row in board:
	list1 = []
	pnum = rnumbers[rcount]
	Pin(pnum, Pin.OUT_PP)
	Pin(pnum).low
	ccount = 0
	for e in row:
		plet = cletters[ccount]
		p_in = Pin(plet, Pin.IN, Pin.PULL_UP)
		board[rcount][ccount] = p_in.value()
		pvalue = p_in.value()
		list1.append(pvalue)
		ccount = ccount + 1
	rcount = rcount + 1
	Pin(pnum).high
	print(list1)

print(board)
What I get when I have a magnet on anything on the A column is:

Code: Select all

>>>
PYB: sync filesystems
PYB: soft reboot
[0, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 1, 1, 1, 1, 1, 1]
[[0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1]]
MicroPython v1.5-100-g57e00ef on 2015-11-08; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>>
Any help or ideas why this happens would be appreciated.
Thanks,
Mike

Re: Chess board array

Posted: Fri Nov 20, 2015 3:48 am
by dhylands
A few things I noticed:

1 - You didn't save the pin object returned from Pin(number, Pin.OUT_PP). You should be storing the pin objects and using those pin objects in the rest of the program, and not reconstructing a Pin object each time.

2 - In the second loop you did:

Code: Select all

for letter in cletters:
   Pin(letter, Pin.OUT_PP)
   Pin(letter).low
Shouldn't that be Pin.IN ?

So you should only need to call Pin(letter, Pin.OUT_PP) 8 times, and Pin(letter, Pin.IN_PP) 8 times, saving the 16 pin objects that are returned.

Re: Chess board array

Posted: Fri Nov 20, 2015 4:20 am
by dhylands
I don't have your board, but I wrote the following:

Code: Select all

from pyb import Pin

cletters = ['Y1', 'Y2', 'Y3', 'Y4', 'Y5', 'Y6', 'Y7', 'Y8']
rnumbers = ['X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X7', 'X8']

board = [[0 for j in range(8)] for i in range(8)]

num_pin = []
let_pin = []

for number in rnumbers:
    pin = Pin(number, Pin.OUT_PP)
    pin.high()
    num_pin.append(pin)

for letter in cletters:
    let_pin.append(Pin(letter, Pin.IN, pull=Pin.PULL_UP))

for rcount in range(8):
    npin = num_pin[rcount]
    npin.low()
    for ccount in range(8):
        board[rcount][ccount] = let_pin[ccount].value()
    npin.high()

for row in board:
    print(row)
and called it chess.py. Running on a pyboard with nothing plugged in yielded:

Code: Select all

>>> import chess
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
I then connected a diode with the band connected to X6 (row 6) and the other end connected to Y5 (column E) and reran:

Code: Select all

>>> import chess
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
and there is a single 0 in row 6, column 5. Connecting multiple diodes gave me multiple zeros in the expected places.

Re: Chess board array

Posted: Fri Nov 20, 2015 11:57 am
by KWingfoot
Thank you Dave! I tested the code you wrote with my board and it works perfect. I appreciate the help and the code I can learn from.
For some reason I was thinking I needed to force each column of letters low again. Now the whole pin assignment thing makes more sense to me too. I like the way you put it into a list.

I like to look at how clean Python code can be when someone else writes it :lol: . I seem to always overthink things.
Any tips on comparing one list of lists to another list of lists? That's my next challenge to determine when a piece moved and then to call it a name "e2e4", etc.

Thanks again,
Mike

Re: Chess board array

Posted: Fri Nov 20, 2015 6:29 pm
by dhylands
I probably would have created a class, but I wanted my example to closely reflect your code, so I tried to minimize the changes.

Using a list of pins seems quite reasonable to me. For the board, I may have chosen a list of ints where each int was a bitmask (that's my C background speaking). A list of lists is probably a more natural way to do things.

Using multi-precsion ints, you could store the entire board in a single integer (64-bits is all that is needed). This might be a useful way to conserve memory. I guess it depends on how many "boards" you need to save.

If you store the boards as ints, then you can exclusive-or 2 ints and the result may contain 2 bits which are on. These will correspond to the source and destination of the piece that was moved. I think that if you take an opponents piece, then only 1 bit will be on.

I think that it could be tricky to figure out how a piece gets taken, unless you follow a protocol like remove the taken piece and move the taker. Since a queen, for example, can move in multiple directions and there might be multiple opponent pieces which could be taken. If you just saw the before and after then you wouldn't necessarily be able to tell which piece was taken. But if you can observe the opponents square momentarily have a piece removed, then it could work.

You still probably need to keep a list of lists of the current pieces on the board so that you know what color and type of piece is in each position.

Re: Chess board array

Posted: Fri Nov 20, 2015 6:43 pm
by KWingfoot
Thank you for the tip. I think I'm going to need to do some research on that as I am just learning. Are you basically saying convert each row, or maybe even the whole board as a hex value? So 00100000 would be 32? I'm trying to figure out once I see a piece going from 32 to 16 how I can say that was a3 to a4.
How would I make this a bitmask? I'm trying to even figure out how to do that instead of updating the list for the row.
Thanks again,
Mike

Re: Chess board array

Posted: Fri Nov 20, 2015 7:18 pm
by dhylands
Well hex is just a representation.

I like to think about it in binary.

Each position on the board would be assigned a position between 0 and 63. If we used the row and column indicies then something like (row * 8) + column (where row goes from 0..7 and column goes from 0..7) would get you this index.

You can then create a bitmask for that one position by using (1 << index) or (1 << ((row * 8) + column).

You could print the board using some code like this:

Code: Select all

>>> board = 0x0000ffffffff0000  # Starting board
>>> board	# Shows decimal representation
281474976645120
>>> bin(board)	 # shows binary representation
'0b111111111111111111111111111111110000000000000000'
>>> hex(board) # shows hexadecimal representation
'0xffffffff0000'
>>> for row in range(8):
...   row_bits = (board >> (row * 8)) & 0xff
...   print('{:08b}'.format(row_bits))
... 
00000000
00000000
11111111
11111111
11111111
11111111
00000000
00000000

Re: Chess board array

Posted: Fri Nov 20, 2015 10:04 pm
by KWingfoot
Thank you for the example and explaining it. That gave me something to think about and digest.
Mike

Re: Chess board array

Posted: Mon Nov 23, 2015 2:10 pm
by KWingfoot
Thanks again Dave. I like the bitboard and was able to make strides in making this work and identify pieces. But, I'm having a problem that seems to be PyBoard specific with if statements in a while loop. In the code below I have an integer I create by taking all the bits from the board first as a string and then turning them into binary. Which, by the way, if there is a better way of doing this I'd love to know.
After creating the integer I do an XOR with the previous state to determine if a bit flipped. My thought is, if this value is 0 nothing happened. But, when I try to use this 0 value in an if statement it doesn't actually work. The integer I'm looking at is "c". I stripped a bunch of code out to show the example:

Code: Select all

from pyb import Pin

cletters = ['Y1', 'Y2', 'Y3', 'Y4', 'Y5', 'Y6', 'Y7', 'Y8']
rnumbers = ['X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X7', 'X8']

board = [[0 for j in range(8)] for i in range(8)]
nboard = []
board3 = []

num_pin = []
let_pin = []
a = ''
b = 0
a_bin = 0
c = 0
d = 0
count = 0
coord = ''
board_count = -1
board_state = []

row_dict = {1:'h', 2:'g', 4:'f', 8:'e', 16:'d', 32:'c', 64:'b', 128:'a'}


for number in rnumbers:
    pin = Pin(number, Pin.OUT_PP)
    pin.high()
    num_pin.append(pin)

for letter in cletters:
    let_pin.append(Pin(letter, Pin.IN, pull=Pin.PULL_UP))


while d == 0:
    b = a_bin
    a = ''
    for rcount in range(8):
        npin = num_pin[rcount]
        npin.low()
        for ccount in range(8):
            a += str(let_pin[ccount].value())
        npin.high()
    a_bin = int(a,2)
    if count == 0:
        b = a_bin
        board1 = b
        board2 = b
        count += 1
    c = a_bin ^ b
    if d != 1:
        print("d != 1")
        print("c = ", c)
    if c != 0:
        print("C != 0")
    if c >= 1:
        print("C >= 1")
    print("c = ", c)
    d = 1
When I run this I get:

Code: Select all

>>> import ctest1
d != 1
c =  0
C != 0
C >= 1
c =  0
>>>
How can these if statements be executed when c equals 0?
When I reconfigure this script to run it on a PC in Python 3 it works correctly and doesn't follow the if c statements.
Is there something I'm missing here? Or does MicroPython work a little different for some reason?
Thank you,
Mike

Re: Chess board array

Posted: Mon Nov 23, 2015 4:51 pm
by dhylands
It turns out that there was a bug on the pyboard relating to exclusive or that was reported yesterday:
https://github.com/micropython/micropython/issues/1622
and fixed:
https://github.com/micropython/micropyt ... 09dca923c0

I suspect that's the issue that you're running into.

The latest nightly image has the fix in it already:
http://micropython.org/download/