New github source

2014-12-23 Thread chris . hinsley
Hellow, just letting people know I've put up some github repo's of my Pthon 
projects:

https://github.com/vygr/Python-PCB
https://github.com/vygr/Python-Chess

Regards

Chris
-- 
https://mail.python.org/mailman/listinfo/python-list


Latest Chess prog

2014-09-03 Thread Chris Hinsley
Latest version of Chess test prog for anyone who might be interested. 
It does not do en-passon or castling.


Best Regards

Chris

#!/opt/local/bin/pypy -u -tt
#!/opt/local/bin/pypy -u -tt -m cProfile
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Chris Hinsley, GPL V3 License

import sys, os, time
from operator import itemgetter
from array import array

MAX_PLY = 10
MAX_TIME_PER_MOVE = 10
PIECE_VALUE_FACTOR = 3

KING_VALUE, QUEEN_VALUE, ROOK_VALUE = 100, 9 * PIECE_VALUE_FACTOR, 
5 * PIECE_VALUE_FACTOR
BISHOP_VALUE, KNIGHT_VALUE, PAWN_VALUE = 3 * PIECE_VALUE_FACTOR, 3 * 
PIECE_VALUE_FACTOR, 1 * PIECE_VALUE_FACTOR


EMPTY, WHITE, BLACK = 0, 1, -1
NO_CAPTURE, MAY_CAPTURE, MUST_CAPTURE = 0, 1, 2

piece_type = {' ' : EMPTY, 'K' : BLACK, 'Q' : BLACK, 'R' : BLACK, 'B' : 
BLACK, 'N' : BLACK, 'P' : BLACK, \
			'k' : WHITE, 'q' : WHITE, 'r' : WHITE, 'b' : WHITE, 'n' : WHITE, 'p' 
: WHITE}


def display_board(board):
print
print '  a   b   c   d   e   f   g   h'
print '+---+---+---+---+---+---+---+---+'
for row in range(8):
for col in range(8):
print '| %c' % board[row * 8 + col],
print '|', 8 - row
print '+---+---+---+---+---+---+---+---+'
print

def piece_moves(board, index, vectors):
piece = board[index]
type = piece_type[piece]
promote = 'QRBN' if type == BLACK else 'qrbn'
cy, cx = divmod(index, 8)
for dx, dy, length, flag in vectors:
x, y = cx, cy
if length == 0:
if piece == 'P':
length = 2 if (y == 1) else 1
else:
length = 2 if (y == 6) else 1
while length  0:
x += dx; y += dy; length -= 1
if (x  0) or (x =8) or (y  0) or (y = 8):
break
newindex = y * 8 + x
newpiece = board[newindex]
newtype = piece_type[newpiece]
if newtype == type:
break
if (flag == NO_CAPTURE) and (newtype != EMPTY):
break
if (flag == MUST_CAPTURE) and (newtype == EMPTY):
break
board[index] = ' '
if (y == 0 or y == 7) and piece in 'Pp':
for promote_piece in promote:
board[newindex] = promote_piece
yield board
else:
board[newindex] = piece
yield board
board[index], board[newindex] = piece, newpiece
if (flag == MAY_CAPTURE) and (newtype != EMPTY):
break

def piece_scans(board, index, vectors):
cy, cx = divmod(index, 8)
for dx, dy, length in vectors:
x, y = cx, cy
while length  0:
x += dx; y += dy; length -= 1
if (0 = x  8) and (0 = y  8):
piece = board[y * 8 + x]
if piece != ' ':
yield piece
break

black_pawn_vectors = [(-1, 1, 1), (1, 1, 1)]
white_pawn_vectors = [(-1, -1, 1), (1, -1, 1)]
bishop_vectors = [(x, y, 7) for x, y in [(-1, -1), (1, 1), (-1, 1), (1, -1)]]
rook_vectors = [(x, y, 7) for x, y in [(0, -1), (-1, 0), (0, 1), (1, 0)]]
knight_vectors = [(x, y, 1) for x, y in [(-2, 1), (2, -1), (2, 1), (-2, 
-1), (-1, -2), (-1, 2), (1, -2), (1, 2)]]

queen_vectors = bishop_vectors + rook_vectors
king_vectors = [(x, y, 1) for x, y, _ in queen_vectors]

black_pawn_moves = [(0, 1, 0, NO_CAPTURE), (-1, 1, 1, MUST_CAPTURE), 
(1, 1, 1, MUST_CAPTURE)]
white_pawn_moves = [(x, -1, length, flag) for x, _, length, flag in 
black_pawn_moves]

rook_moves = [(x, y, length, MAY_CAPTURE) for x, y, length in rook_vectors]
bishop_moves = [(x, y, length, MAY_CAPTURE) for x, y, length in bishop_vectors]
knight_moves = [(x, y, length, MAY_CAPTURE) for x, y, length in knight_vectors]
queen_moves = bishop_moves + rook_moves
king_moves = [(x, y, 1, flag) for x, y, _, flag in queen_moves]

moves = {'P' : black_pawn_moves, 'p' : white_pawn_moves, 'R' : 
rook_moves, 'r' : rook_moves, \
		'B' : bishop_moves, 'b' : bishop_moves, 'N' : knight_moves, 'n' : 
knight_moves, \

'Q' : queen_moves, 'q' : queen_moves, 'K' : king_moves, 'k' : 
king_moves}

white_scans = [('QB', bishop_vectors), ('QR', rook_vectors), ('N', 
knight_vectors), ('K', king_vectors), ('P', white_pawn_vectors)]
black_scans = [('qb', bishop_vectors), ('qr', rook_vectors), ('n', 
knight_vectors), ('k

Re: First attempt at a Python prog (Chess)

2014-04-30 Thread Chris Hinsley

On 2013-02-15 05:05:27 +, Rick Johnson said:


On Thursday, February 14, 2013 11:48:10 AM UTC-6, Chris Hinsley wrote:


Is a Python list as fast as a bytearray?


Why would you care about that now? Are you running this code on the 
Xerox Alto? Excuse me for the sarcasm but your post title has perplexed 
me:


 First attempt at a Python prog (Chess)Okay, but how does that translate to:
The fastest, most efficient, most brain fricked python code ever 
released in the form of a game, that just happens to look an awful lot 
like C source?

http://en.wikipedia.org/wiki/Optimization_%28computer_science%29#When_to_optimize 



Why bother to use Python if what you really want to write is C code? If 
you want to write good code (not just python), you need to write code 
that is maintainable. Yes i KNOW, this is just some stupid chess game, 
but i can assure you that this style of code is only going to harm your 
evolution. This code is obfuscated at best and BF'ed at worst. And 
forget about the algorithms for now, the first problems to address are 
superficial.


First of all your naming conventions suck. You've used the interface 
style for every function in this game so i can't /easily/ eyeball parse 
the /real/ interface functions from the helper functions -- and i'm not 
going to even try, because i don't read ugly code! Try to learn the 
Python style guide as soon as you can (In particular pay attention to 
naming conventions):


 http://www.python.org/dev/peps/pep-0008/

Secondly this game could benefit from some OOP paradigm (not sure if 
are familiar with OOP or not???). But don't go bat-crazy with OOP! You 
don't need an object to represent /every/ single piece on the board 
(That would be nuts!). You need just enough OOP to encapsulate the data 
and create a proper interface.

A good litmus test is based on the three little bears:

 Papa bears bed is too hard

A hard utilization of paradigms wields too little OOP and therefore 
ends up being too difficult (aka: hard) to maintain because there is 
no logical interface; just a massive collection of functions stuffed 
into global space until BF reaches critical mass and you're forced to 
do a complete re-write! (Of course sometimes you don't need OOP at all, 
just interface)

 Mama bears bed is too soft

A soft utilization of paradigms wields too much OOP whereby you are 
surrounded by big FAT objects which are smothering you to death, and 
they smell because they cannot properly wash themselves between the 
rolls of fat.


 but baby bears is just right
Ahhh, the blissful comfort of a paradigm utilization that is just 
right. This is where your code should be, you want a level of OOP 
usage that is just right for the occasion; not any more, not any less.

## START EXAMPLE CODE ##
class GameBoard(???):
def __init__(self):
self.board = self._createBoard()
   def __str__(self):
Override:
# return a string represention of the board
# suitable for writing to stdout
   def _createBoard(self):
Internal:
self.board = [blah]
  def make_move(self, piece, vector):
Interface: move a game piece based on vector
# Find and move the piece. Whether the pieces
# are objects or not doesn't matter.
   class GamePiece(object):
def __init__(self, typename, color):
self.typeName = typeName
self.color = color
self.captureFlag = self._computeFlag()


def main():
board = Board()
playing = True
while playing is not False
i = input('PieceName - MoveVec:')
n, v = parse(i)
result = board.make_move(n, v)
if result == 'GameOver':
playing = False
else:
# clear the stdout
str(board)

if __name__ == '__main__:
main()
## END EXAMPLE CODE ##

And now you have the added benefit of exporting the objects for use elsewhere.


Wow, such vitriol for such a simple bear to cope with !

Maybe Papa bear would like to try some humility !

This was my very first Python prog, and my first chess prog and my 
attempt to learn somthing about Generators ! Do youtself a favour and 
leave the Python comunity for the good of the language !


Chris

--
https://mail.python.org/mailman/listinfo/python-list


Re: odd behavoiur seen

2013-07-22 Thread Chris Hinsley

On 2013-07-22 18:36:41 +, Chris Hinsley said:


Folks, I have this decorator:

def memoize(maxsize):
def _memoize(func):
lru_cache = {}
lru_list = []


Other clues, I use it on a recursive function:

@memoize(64)
def next_move(board, colour, alpha, beta, ply):
   if ply = 0:
   return evaluate(board) * colour
   for new_board in all_moves(board[:], colour):
   score = -next_move(new_board, -colour, -beta, -alpha, ply - 1)
   if score = beta:
   return score
   if score  alpha:
   alpha = score
   return alpha

And I notice I don't get the strange problem on a non-recursive 
function ! Or at least I don't seam to.


Chris

--
http://mail.python.org/mailman/listinfo/python-list


odd behavoiur seen

2013-07-22 Thread Chris Hinsley

Folks, I have this decorator:

def memoize(maxsize):
   def _memoize(func):
   lru_cache = {}
   lru_list = []

   def memoizer(*args, **kwargs):
   key = str(args) + str(kwargs)
   if key in lru_cache:
   lru_list.remove(key)
   lru_list.append(key)
   return lru_cache[key]
   print len(lru_list),
   if len(lru_list) = maxsize:
   del(lru_cache[lru_list[0]])
   del(lru_list[0])
   ret = func(*args, **kwargs)
   lru_cache[key] = ret
   lru_list.append(key)
   return ret
   return memoizer
   return _memoize

I didn't used to do the 'len(lru_list) = maxsize' just '==' and 
noticed it sailing past the max number of entries, so put in the print 
statement, and now I see it ocationally printing a value 1 larger than 
maxsize !!!


So if I use it as '@memoize(64)' I see some 65's in the output ! I'm at 
a loss to explain it, does anyone knows why ? Is it a bug or some 
threading issue ? I'm not useing threads BTW, and I've noticed this in 
both running it with Python or Pypy.


Best Regards

Chris

--
http://mail.python.org/mailman/listinfo/python-list


Re: odd behavoiur seen

2013-07-22 Thread Chris Hinsley

On 2013-07-22 19:47:33 +, Peter Otten said:


Chris Hinsley wrote:


On 2013-07-22 18:36:41 +, Chris Hinsley said:


Folks, I have this decorator:

def memoize(maxsize):
def _memoize(func):
lru_cache = {}
lru_list = []


Other clues, I use it on a recursive function:

@memoize(64)
def next_move(board, colour, alpha, beta, ply):
if ply = 0:
return evaluate(board) * colour
for new_board in all_moves(board[:], colour):
score = -next_move(new_board, -colour, -beta, -alpha, ply - 1)
if score = beta:
return score
if score  alpha:
alpha = score
return alpha

And I notice I don't get the strange problem on a non-recursive
function ! Or at least I don't seam to.


That's indeed the problem:


if len(lru_list) = maxsize:
del(lru_cache[lru_list[0]])
del(lru_list[0])
ret = func(*args, **kwargs)
lru_cache[key] = ret
lru_list.append(key)


You delete a cached item, then call the original function which causes calls
of the decorated function. This causes a length check which sees the already
reduced length and decides that the cache is not yet full.

If you remove the oldest item after calling the original function you should
be OK.


Ah ! Thank you kindly sir !

Chris

--
http://mail.python.org/mailman/listinfo/python-list


Re: First attempt at a Python prog (Chess)

2013-07-04 Thread Chris Hinsley

On 2013-02-13 23:25:09 +, Chris Hinsley said:


New to Python, which I really like BTW.

First serious prog. Hope you like it. I know it needs a 'can't move if 
your King would be put into check' test. But the weighted value of the 
King piece does a surprising emergent job.


New version with better search and hopefully a little better Python. I 
know it's still far from fully correct and it'll never best Gary 
Kasperov. :)


With pypy on my Macbook I can go to 6 PLY with resonable performance 
now due to the alpha-beta pruneing.


Regards

#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
# Copyright (C) 2013 Chris Hinsley, GPL V3 License

import sys
import random
import os

PLY = 5

EMPTY = 0
WHITE = 1
BLACK = -1
NO_CAPTURE = 2
MAY_CAPTURE = 3
MUST_CAPTURE = 4

piece_type = {' ' : EMPTY, 'K' : BLACK, 'Q' : BLACK, 'R' : BLACK, 'B' : 
BLACK, 'N' : BLACK, 'P' : BLACK, \
   'k' : WHITE, 'q' : WHITE, 'r' : WHITE, 'b' : WHITE, 'n' : 
WHITE, 'p' : WHITE}


def display_board(board):
   print '  a   b   c   d   e   f   g   h'
   print '+---+---+---+---+---+---+---+---+'
   for row in range(8):
   for col in range(8):
   print '| %c' % board[row * 8 + col],
   print '|', 8 - row
   print '+---+---+---+---+---+---+---+---+'

def piece_moves(board, index, dx, dy, capture_flag, distance):
   piece = board[index]
   type = piece_type[piece]
   cy, cx = divmod(index, 8)
   for step in range(distance):
   nx = cx + (dx * (step + 1))
   ny = cy + (dy * (step + 1))
   if (0 = nx  8) and (0 = ny  8):
   newindex = ny * 8 + nx
   newpiece = board[newindex]
   newtype = piece_type[newpiece]
   if capture_flag == MUST_CAPTURE:
   if newtype != EMPTY and newtype != type:
   board[index] = ' '
   if (ny == 0 or ny == 7) and piece in 'Pp':
   for promote in 'QRBN' if type == BLACK else 'qrbn':
   board[newindex] = promote
   yield board
   else:
   board[newindex] = piece
   yield board
   board[index], board[newindex] = piece, newpiece
   elif capture_flag == MAY_CAPTURE:
   if newtype == EMPTY:
   board[index], board[newindex] = ' ', piece
   yield board
   board[index], board[newindex] = piece, newpiece
   elif newtype != type:
   board[index], board[newindex] = ' ', piece
   yield board
   board[index], board[newindex] = piece, newpiece
   break
   else:
   break
   elif newtype == EMPTY:
   board[index] = ' '
   if (ny == 0 or ny == 7) and piece in 'Pp':
   for promote in 'QRBN' if type == BLACK else 'qrbn':
   board[newindex] = promote
   yield board
   else:
   board[newindex] = piece
   yield board
   board[index], board[newindex] = piece, newpiece
   else:
   break
   else:
   break

def pawn_moves(board, index, options):
   for x, y, flag, distance in options:
   for new_board in piece_moves(board, index, x, y, flag, distance):
   yield new_board

def other_moves(board, index, options, distance):
   for x, y in options:
   for new_board in piece_moves(board, index, x, y, MAY_CAPTURE, 
distance):

   yield new_board

def black_pawn_moves(board, index):
   distance = 2 if index in range(8, 16) else 1
   for new_board in pawn_moves(board, index, [(0, 1, NO_CAPTURE, 
distance), (-1, 1, MUST_CAPTURE, 1), (1, 1, MUST_CAPTURE, 1)]):

   yield new_board

def white_pawn_moves(board, index):
   distance = 2 if index in range(48, 56) else 1
   for new_board in pawn_moves(board, index, [(0, -1, NO_CAPTURE, 
distance), (-1, -1, MUST_CAPTURE, 1), (1, -1, MUST_CAPTURE, 1)]):

   yield new_board

def rook_moves(board, index):
   for new_board in other_moves(board, index, [(0, -1), (-1, 0), (0, 
1), (1, 0)], 7):

   yield new_board

def bishop_moves(board, index):
   for new_board in other_moves(board, index, [(-1, -1), (-1, 1), (1, 
1), (1, -1)], 7):

   yield new_board

def knight_moves(board, index):
   for new_board in other_moves(board, index, [(-2, 1), (2, -1), (2, 
1), (-1, -2), (-1, 2), (1, -2), (1, 2)], 1):

   yield new_board

def queen_moves(board, index):
   for new_board in bishop_moves(board, index):
   yield new_board
   for new_board in rook_moves(board, index):
   yield new_board

def king_moves(board, index):
   for new_board in other_moves(board, index, [(0, -1), (-1, 0), (0, 
1), (1, 0), (-1, -1), (-1, 1), (1, 1), (1, -1)], 1):

   yield new_board

moves = {'P' : black_pawn_moves, 'p' : white_pawn_moves, \
   'R' : rook_moves, 'r' : rook_moves, \
   'B

Re: First attempt at a Python prog (Chess)

2013-02-14 Thread Chris Hinsley

On 2013-02-14 06:05:13 +, Tim Roberts said:


Chris Hinsley chris.hins...@gmail.com wrote:


New to Python, which I really like BTW.

First serious prog. Hope you like it. I know it needs a 'can't move if
your King would be put into check' test. But the weighted value of the
King piece does a surprising emergent job.


It looks a little like a C program ported line-by-line to Python.  For
example, in Python, there's no reason not to keep the board as an 8x8 array
instead of a 64-element list.  That by itself would make the code easier to
read.  It would also let you replace this:
for row in range(8):
for col in range(8):

with the more Pythonic:
for row in board:
for cell in row:

I would probably replace the piece_type function with a map that maps the
piece number directly to the piece


Is a Python list as fast as a bytearray ? I didn't copy a C prog BTW !

Yep, after I posted the code I started thinking about how to do that 
sort of thing :) Thanks, for the advice.


Chris

--
http://mail.python.org/mailman/listinfo/python-list


Re: First attempt at a Python prog (Chess)

2013-02-14 Thread Chris Hinsley

On 2013-02-14 21:14:03 +, jkn said:


Hi Chris

On Wednesday, 13 February 2013 23:25:09 UTC, Chris Hinsley  wrote:

New to Python, which I really like BTW.


Welcome aboard! But aren't you supposed to be writing Forth? ;-)

Cheers
Jon N



Well, I'm experimenting with other things too ! :) I might yet even 
have another bash at Lisp...


Chris

--
http://mail.python.org/mailman/listinfo/python-list


First attempt at a Python prog (Chess)

2013-02-13 Thread Chris Hinsley

New to Python, which I really like BTW.

First serious prog. Hope you like it. I know it needs a 'can't move if 
your King would be put into check' test. But the weighted value of the 
King piece does a surprising emergent job.


#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
# Copyright (C) 2013 Chris Hinsley, GPL V3 License

import sys
import random
import os

PLY = 3

EMPTY = 0
BLACK = 1
WHITE = 2
NO_CAPTURE = 3
MAY_CAPTURE = 4
MUST_CAPTURE = 5

def piece_type(piece):
   return EMPTY if piece == 32 else BLACK if chr(piece) in 'KQRBNP' else WHITE

def display_board(board):
   print '  a   b   c   d   e   f   g   h'
   print '+---+---+---+---+---+---+---+---+'
   for row in range(8):
   for col in range(8):
   sys.stdout.write('| ')
   sys.stdout.write(chr(board[row * 8 + col]))
   sys.stdout.write(' ')
   sys.stdout.write('|')
   print 8 - row
   print '+---+---+---+---+---+---+---+---+'

def piece_moves(board, index, dx, dy, capture_flag, distance):
   piece = board[index]
   type = piece_type(piece)
   cx = index % 8
   cy = index / 8
   for step in range(distance):
   nx = cx + (dx * (step + 1))
   ny = cy + (dy * (step + 1))
   if nx in range(8) and ny in range(8):
   newindex = ny * 8 + nx
   newpiece = board[newindex]
   newtype = piece_type(newpiece)
   if capture_flag == MUST_CAPTURE:
   if newtype != EMPTY and newtype != type:
   board[index] = ' '
   if (ny == 0 or ny == 7) and chr(piece) in 'Pp':
   for promote in 'QRBN' if type == BLACK else 'qrbn':
   board[newindex] = promote
   yield board
   else:
   board[newindex] = piece
   yield board
   board[index], board[newindex] = piece, newpiece
   elif capture_flag == MAY_CAPTURE:
   if newtype == EMPTY or newtype != type:
   board[index], board[newindex] = ' ', piece
   yield board
   board[index], board[newindex] = piece, newpiece
   break
   elif newtype == EMPTY:
   board[index] = ' '
   if (ny == 0 or ny == 7) and chr(piece) in 'Pp':
   for promote in 'QRBN' if type == BLACK else 'qrbn':
   board[newindex] = promote
   yield board
   else:
   board[newindex] = piece
   yield board
   board[index], board[newindex] = piece, newpiece
   else:
   break

def pawn_moves(board, index, options):
   for x, y, flag, distance in options:
   for new_board in piece_moves(board, index, x, y, flag, distance):
   yield new_board

def other_moves(board, index, options, distance):
   for x, y in options:
   for new_board in piece_moves(board, index, x, y, MAY_CAPTURE, 
distance):

   yield new_board

def black_pawn_moves(board, index):
   distance = 2 if index in range(8, 16) else 1
   for new_board in pawn_moves(board, index, [(0, 1, NO_CAPTURE, 
distance), (-1, 1, MUST_CAPTURE, 1), (1, 1, MUST_CAPTURE, 1)]):

   yield new_board

def white_pawn_moves(board, index):
   distance = 2 if index in range(48, 56) else 1
   for new_board in pawn_moves(board, index, [(0, -1, NO_CAPTURE, 
distance), (-1, -1, MUST_CAPTURE, 1), (1, -1, MUST_CAPTURE, 1)]):

   yield new_board

def rook_moves(board, index):
   for new_board in other_moves(board, index, [(0, -1), (-1, 0), (0, 
1), (1, 0)], 7):

   yield new_board

def bishop_moves(board, index):
   for new_board in other_moves(board, index, [(-1, -1), (-1, 1), (1, 
1), (1, -1)], 7):

   yield new_board

def knight_moves(board, index):
   for new_board in other_moves(board, index, [(-2, 1), (2, -1), (2, 
1), (-1, -2), (-1, 2), (1, -2), (1, 2)], 1):

   yield new_board

def queen_moves(board, index):
   for new_board in bishop_moves(board, index):
   yield new_board
   for new_board in rook_moves(board, index):
   yield new_board

def king_moves(board, index):
   for new_board in other_moves(board, index, [(0, -1), (-1, 0), (0, 
1), (1, 0), (-1, -1), (-1, 1), (1, 1), (1, -1)], 1):

   yield new_board

moves = {'P' : black_pawn_moves, 'p' : white_pawn_moves, \
   'R' : rook_moves, 'r' : rook_moves, \
   'B' : bishop_moves, 'b' : bishop_moves, \
   'N' : knight_moves, 'n' : knight_moves, \
   'Q' : queen_moves, 'q' : queen_moves, \
   'K' : king_moves, 'k' : king_moves}

def all_moves(board, turn):
   for index, piece in enumerate(board):
   if piece_type(piece) == turn:
   for new_board in moves[chr(piece)](board, index):
   yield new_board

piece_values = {'K' : (100, 0), 'k' : (0, 100), \
   'P' : (1, 0), 'p' : (0, 1), \
   'N' : (3, 0), 'n' : (0, 3), \
   'B' : (3, 0), 'b' : (0, 3

Re: First attempt at a Python prog (Chess)

2013-02-13 Thread Chris Hinsley

On 2013-02-13 23:55:20 +, Oscar Benjamin said:


On 13 February 2013 23:25, Chris Hinsley chris.hins...@gmail.com wrote:

New to Python, which I really like BTW.


Glad to hear it.


First serious prog. Hope you like it. I know it needs a 'can't move if your
King would be put into check' test. But the weighted value of the King piece
does a surprising emergent job.

[SNIP program]

Your program looks good. Were you looking for feedback (I'm sure
someone would give some if so)?


Oscar


I suppose so yes. I was just 'putting it out there' to see if it was 
interesting/useful to anyone. No doubt there are many Python features I 
could use to improve on this. First thing that occurred to me on 
deciding to try Python was the idea of Generator functions to enumerate 
all the possible moves of a Chess game, and that 'yield' would make the 
prog relatively compact.


I wish Shedskin could cope with them ! PyPy runs it OK.

Chris

--
http://mail.python.org/mailman/listinfo/python-list