Re: First attempt at a Python prog (Chess)

2014-04-30 Thread Robert Kern

On 2014-04-30 16:15, Mark H Harris wrote:

On 4/30/14 8:28 AM, Chris Hinsley wrote:

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


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):



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



Chris, you might want to try another list:

https://mail.python.org/mailman/listinfo/tutor


The folks on this list are friendly, but tough. They are not generally arrogant,
but many of them are experts (or core python developers) and most of them are
worth listening to. The list mentioned above is for folks who are learning
python and who have basic questions or want basic clarifications.   (they are
gentler too):)


It's also worth noting that Rick Johnson is a well-known troll here and *not* 
representative of this group. He was deliberately insulting Chris, not being 
"tough" but helpful. He is not worth listening to. He is to be killfiled and 
ignored. Chris, I'm sorry you ran into him on your first introduction to this 
community.


--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
 that is made terrible by our own mad attempt to interpret it as though it had
 an underlying truth."
  -- Umberto Eco

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


Re: First attempt at a Python prog (Chess)

2014-04-30 Thread Mark H Harris

On 4/30/14 8:28 AM, Chris Hinsley wrote:

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


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):



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



Chris, you might want to try another list:

https://mail.python.org/mailman/listinfo/tutor


The folks on this list are friendly, but tough. They are not generally 
arrogant, but many of them are experts (or core python developers) and 
most of them are worth listening to. The list mentioned above is for 
folks who are learning python and who have basic questions or want basic 
clarifications.   (they are gentler too):)



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


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: First attempt at a Python prog (Chess)

2013-07-04 Thread Joshua Landau
Just a minor suggestion:

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

  if piece_type[piece] == WHITE:
print '| \x1b[31;01m%c\x1b[39;49;00m' % board[row * 8 + col],

  else:
print '| \x1b[34;01m%c\x1b[39;49;00m' % board[row * 8 + col],

  print '|', 8 - row

  print '+---+---+---+---+---+---+---+---+'
-- 
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-19 Thread Neil Cerutti
On 2013-02-15, MRAB  wrote:
> On 2013-02-15 16:17, Neil Cerutti wrote:
>> On 2013-02-15, Oscar Benjamin  wrote:
>>> if score > best_score or best_score is None:
>>
>> You need the None check first to avoid an exception from the
>> comparison.
>
> Only in Python 3.

It is a more difficult to find bug in Python 2, which will not
even throw an exception, but instead silently do the wrong thing.

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


Re: First attempt at a Python prog (Chess)

2013-02-19 Thread Ian Kelly
On Mon, Feb 18, 2013 at 9:15 PM, Tim Roberts  wrote:
> Chris Hinsley  wrote:
>>
>>Is a Python list as fast as a bytearray ?
>
> Python does not actually have a native array type.  Everything in your
> program that looked like an array was actually a list.

How do you mean?

>>> isinstance(bytearray(b'RNBQKBNR'), list)
False
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: First attempt at a Python prog (Chess)

2013-02-18 Thread Steven D'Aprano
On Mon, 18 Feb 2013 20:15:28 -0800, Tim Roberts wrote:

> Chris Hinsley  wrote:
>>
>>Is a Python list as fast as a bytearray ?
> 
> Python does not actually have a native array type.  Everything in your
> program that looked like an array was actually a list.

Actually it does, but you have to import it first, it is not a built-in 
data type.


py> import array
py> arr = array.array('f')  # array of floats (C singles)
py> arr.append(0.1)
py> arr.append(0.2)
py> print(arr)
array('f', [0.1000149011612, 0.2000298023224])
py> arr.append("foo")
Traceback (most recent call last):
  File "", line 1, in 
TypeError: a float is required


See the documentation for array to see the available type-codes.

http://docs.python.org/2/library/array.html
http://docs.python.org/3/library/array.html

As part of the standard library, Jython and IronPython are required to 
implement arrays as well (although they don't use C arrays, so the 
implementation may be different).

http://www.jython.org/docs/library/array.html
http://ironpython-test.readthedocs.org/en/latest/library/array.html

IronPython also gives you access to .Net arrays, although of course that 
is not standard Python:

http://www.ironpython.info/index.php/Typed_Arrays_in_IronPython



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


Re: First attempt at a Python prog (Chess)

2013-02-18 Thread Tim Roberts
Chris Hinsley  wrote:
>
>Is a Python list as fast as a bytearray ?

Python does not actually have a native array type.  Everything in your
program that looked like an array was actually a list.
-- 
Tim Roberts, t...@probo.com
Providenza & Boekelheide, Inc.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: First attempt at a Python prog (Chess)

2013-02-16 Thread Oscar Benjamin
On 15 February 2013 15:49, Chris Angelico  wrote:
> On Sat, Feb 16, 2013 at 2:36 AM, Tim Golden  wrote:
>> How true. This last time, my team split into two: one half
>> to handle the display, the other working on the algorithm. We
>> ended up having to draw a really simple diagram on the back of
>> an envelope with the x,y pairs written out and pass it back
>> and forth as *everyone* kept forgetting which went first.
>
> I'm sorry, I don't follow. People forgot that x comes before y, like
> it does in everything algebraic? Or is it that people lost track of
> which axis you called 'x' and which you called 'y'?

When you have a flat array and need to do a[x*N + y] to get an
element, the order is irrelevant. What matters is which of the
coordinates you multiply and what dimension of the array you multiply
it by. There are two equally good ways to do this, row-major and
column-major order:
http://en.wikipedia.org/wiki/Row-major_order

Any time you call into an API that expects a flattened array
representing a multidimensional array you need to check what order the
API expects. Typically a language has a convention such as C
(row-major) or Fortran (column-major). (According to that Wikipedia
page Python uses row-major, but I'm not really sure what that is
referring to).

Numpy allows you to specify the order when creating an array:
>>> import numpy as np
>>> aC = np.array([['a', 'b'], ['c', 'd']], dtype=str, order='C')
>>> aF = np.array([['a', 'b'], ['c', 'd']], dtype=str, order='F')
>>> aC
array([['a', 'b'],
   ['c', 'd']],
  dtype='|S1')
>>> aF
array([['a', 'b'],
   ['c', 'd']],
  dtype='|S1')

The different order in the two arrays above is transparent to Python
code that doesn't directly refer to the underlying memory arrangement:

>>> aC[0, 1]
'b'
>>> aF[0, 1]
'b'
>>> aC.strides
(2, 1)
>>> aF.strides
(1, 2)
>>> str(buffer(aC))
'abcd'
>>> str(buffer(aF))
'acbd'

This is useful when interfacing with linked Fortran and C libraries
(as is the case in scipy).

I find keeping track of what order I'm using when accessing the
elements of an array to be a pointless distraction. I would much
rather use an abstraction over the linear memory (such as a numpy
array) that enables me to forget all about it.


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


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Matt Jones
"Only in Python 3."

Use best practices always, not just when you have to.

*Matt Jones*


On Fri, Feb 15, 2013 at 11:52 AM, MRAB  wrote:

> On 2013-02-15 16:17, Neil Cerutti wrote:
>
>> On 2013-02-15, Oscar Benjamin  wrote:
>>
>>> if score > best_score or best_score is None:
>>>
>>
>> You need the None check first to avoid an exception from the
>> comparison.
>>
>>  Only in Python 3.
>
>
>  if best_score is None or score > best_score:
>>
>>
> --
> http://mail.python.org/**mailman/listinfo/python-list
>
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread MRAB

On 2013-02-15 16:17, Neil Cerutti wrote:

On 2013-02-15, Oscar Benjamin  wrote:

if score > best_score or best_score is None:


You need the None check first to avoid an exception from the
comparison.


Only in Python 3.


if best_score is None or score > best_score:



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


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Tim Golden

On Sat, Feb 16, 2013 at 2:36 AM, Tim Golden  wrote:

How true. This last time, my team split into two: one half
to handle the display, the other working on the algorithm. We
ended up having to draw a really simple diagram on the back of
an envelope with the x,y pairs written out and pass it back
and forth as *everyone* kept forgetting which went first.






On 15/02/2013 15:49, Chris Angelico wrote:

I'm sorry, I don't follow. People forgot that x comes before y, like
it does in everything algebraic? Or is it that people lost track of
which axis you called 'x' and which you called 'y'?



> On 15/02/2013 16:48, Jussi Piitulainen wrote:
> Surely you knew to have f1(board, x, y) for getting whatever is at
> (x,y) and f2(store, x, y, wev) for putting wev at (x,y). Why didn't
> you do that?

To be honest I don't remember exactly what we did get confused
over; it was probably whether our origin was top left and/or
whether we were storing in row or in column order. But in any
case, my experience is that stuff which is perfectly easy to
reason about and write as Jussi has above when you're just
coding quietly on your own becomes a confused ball of mess as
soon as you're part of a Dojo team with 60 minutes to come up
with a solution. (Not saying that we couldn't have managed better;
merely that we didn't).

TJG


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


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Jussi Piitulainen
Tim Golden writes:
> On 15/02/2013 13:11, Oscar Benjamin wrote:
> > On 15 February 2013 11:36, Tim Golden wrote:
> >> And the "how shall we represent the board?" question is pretty
> >> much the first thing any team asks themselves. And you always get
> >> someone in favour of lists of lists, someone for one long list,
> > 
> > I always get confused when doing this about which of my
> > coordinates needs to be multiplied (i.e. whether I am in Fortran
> > or C order).
> 
> How true. This last time, my team split into two: one half to handle
> the display, the other working on the algorithm. We ended up having
> to draw a really simple diagram on the back of an envelope with the
> x,y pairs written out and pass it back and forth as *everyone* kept
> forgetting which went first.

Surely you knew to have f1(board, x, y) for getting whatever is at
(x,y) and f2(store, x, y, wev) for putting wev at (x,y). Why didn't
you do that?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Neil Cerutti
On 2013-02-15, Oscar Benjamin  wrote:
> if score > best_score or best_score is None:

You need the None check first to avoid an exception from the
comparison.

if best_score is None or score > best_score:

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


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Chris Angelico
On Sat, Feb 16, 2013 at 2:36 AM, Tim Golden  wrote:
> How true. This last time, my team split into two: one half
> to handle the display, the other working on the algorithm. We
> ended up having to draw a really simple diagram on the back of
> an envelope with the x,y pairs written out and pass it back
> and forth as *everyone* kept forgetting which went first.

I'm sorry, I don't follow. People forgot that x comes before y, like
it does in everything algebraic? Or is it that people lost track of
which axis you called 'x' and which you called 'y'?

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


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Tim Golden
On 15/02/2013 13:11, Oscar Benjamin wrote:
> On 15 February 2013 11:36, Tim Golden  wrote:
>> And the "how shall we represent the board?" question is pretty
>> much the first thing any team asks themselves. And you always
>> get someone in favour of lists of lists, someone for one long
>> list,
> 
> I always get confused when doing this about which of my coordinates
> needs to be multiplied (i.e. whether I am in Fortran or C order).

How true. This last time, my team split into two: one half
to handle the display, the other working on the algorithm. We
ended up having to draw a really simple diagram on the back of
an envelope with the x,y pairs written out and pass it back
and forth as *everyone* kept forgetting which went first.

>> (Also I seem to remember that the OP was advised earlier precisely
>> to abandon lists of lists in favour of something else).
> 
> Actually the suggestion was for the list of lists (instead of a flat list).

Ah, ok. I'd only followed the thread casually. (And I was too lazy to
go back and check).

TJG

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


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Oscar Benjamin
On 15 February 2013 11:36, Tim Golden  wrote:
> On 15/02/2013 11:22, Oscar Benjamin wrote:
>> Why not make board a list of lists. Then you can do:
>>
>> for row in board:
>> for piece in row:
>>
>> rather than using range().
>>
>> Or perhaps you could have a dict that maps position tuples to pieces,
>> e.g.: {(1, 2): 'k', ...}
>
> I'm laughing slightly here because, at the monthly London Python
> Dojo, we often find ourselves implementing board-game mechanics
> of one sort or another: Boggle, Battleships, Sliding block,
> Connect 4, Noughts-and-Crosses, even things like Game of Life
> (which has a board of sorts).
>
> And the "how shall we represent the board?" question is pretty
> much the first thing any team asks themselves. And you always
> get someone in favour of lists of lists, someone for one long
> list,

I always get confused when doing this about which of my coordinates
needs to be multiplied (i.e. whether I am in Fortran or C order).

> someone who likes a string, someone (me) who likes a sparse
> dict keyed on coords,

Clearly better than the others.

> someone else likes nested defaultdicts,
> and occasionally more outlandish schemes.
>
> We even went to the extent of having a Dojo a few months back
> which was solely about implementing the ideal board for varying
> characteristics, but we didn't come to any conclusions :)

In this case the innermost loop of the program is over the pieces on
the board. Clearly you want a data structure that allows you to
iterate directly over them. (Actually since that loop is to calculate
the score I would replace it with a function that computes the change
in score as a result of each move).

> (Also I seem to remember that the OP was advised earlier precisely
> to abandon lists of lists in favour of something else).

Actually the suggestion was for the list of lists (instead of a flat list).


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


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Tim Golden
On 15/02/2013 11:22, Oscar Benjamin wrote:
> Why not make board a list of lists. Then you can do:
> 
> for row in board:
> for piece in row:
> 
> rather than using range().
> 
> Or perhaps you could have a dict that maps position tuples to pieces,
> e.g.: {(1, 2): 'k', ...}


I'm laughing slightly here because, at the monthly London Python
Dojo, we often find ourselves implementing board-game mechanics
of one sort or another: Boggle, Battleships, Sliding block,
Connect 4, Noughts-and-Crosses, even things like Game of Life
(which has a board of sorts).

And the "how shall we represent the board?" question is pretty
much the first thing any team asks themselves. And you always
get someone in favour of lists of lists, someone for one long
list, someone who likes a string, someone (me) who likes a sparse
dict keyed on coords, someone else likes nested defaultdicts,
and occasionally more outlandish schemes.

We even went to the extent of having a Dojo a few months back
which was solely about implementing the ideal board for varying
characteristics, but we didn't come to any conclusions :)

(Also I seem to remember that the OP was advised earlier precisely
to abandon lists of lists in favour of something else).

TJG

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


Re: First attempt at a Python prog (Chess)

2013-02-15 Thread Oscar Benjamin
On 13 February 2013 23:25, Chris Hinsley  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.
>
> #!/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

You call chr(piece) many times in this program. It would be better to
just have piece be a string rather than always converting it to one
every time you want to do something. Also comparing it with a numeric
code is fairly cryptic. I guess that ascii 32 is a space character but
I'd have to look that up to be sure.

>
> def display_board(board):
>print '  a   b   c   d   e   f   g   h'
>print '+---+---+---+---+---+---+---+---+'
>for row in range(8):
>for col in range(8):

Why not make board a list of lists. Then you can do:

for row in board:
for piece in row:

rather than using range().

Or perhaps you could have a dict that maps position tuples to pieces,
e.g.: {(1, 2): 'k', ...}

>sys.stdout.write('| ')
>sys.stdout.write(chr(board[row * 8 + col]))
>sys.stdout.write(' ')
>sys.stdout.write('|')
>print 8 - row
>print '+---+---+---+---+---+---+---+---+'

You seem to be using sys.stdout.write as a way of printing without a
trailing newline. In Python 2 you can get this effect by using:
print 'foo',

(note the trailing comma). In Python 3 you would do

   print('foo', end=' ')

You can use the Python 3 syntax in your Python 2 script if you do
"from __future__ import print_function" so that your script works on
Python 2 and 3.

Also I would probably separate the function that generates the text
representing the board from the code that actually sends that
information to stdout.


>
> def piece_moves(board, index, dx, dy, capture_flag, distance):
>piece = board[index]
>type = piece_type(piece)
>cx = index % 8
>cy = index / 8

You can use divmod for this:
cx, cy = divmod(index, 8)

Also in Python 3 index / 8 will return a float. Use // for floor
division in both versions ("from __future__ import division").

>for step in range(distance):
>nx = cx + (dx * (step + 1))
>ny = cy + (dy * (step + 1))

Why not make a function that yields these values and loop over that?

def continued_moves(x, y, dx, dy):
while 0 <= x < 8 and 0 <= y < 8:
x += dx
y += dy
yield x, y

>if nx in range(8) and ny in range(8):

Use chained comparisons 0 <= x < 8 rather than testing for membership
in a range object. "x in range(N, M)" creates (in Python 2) a list
integers and then (in 2 or 3) iterates over that list to find an
object equal to x. This is inefficient and not as clear.

>newindex = ny * 8 + nx
>newpiece = board[newindex]

With a list of lists you could access the board with board[ny][nx]
which is clearer. Or with the dict: board[(nx, ny)].

The code below is overly indented. consider factoring it into functions.

>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

Rather than modifying and unmodifying the board in place (which is
fragile), could you not just have the compute_score function compute
the score as if the move had taken place? Then you could just yield
the move and the score.

>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
>

Re: First attempt at a Python prog (Chess)

2013-02-14 Thread Rick Johnson
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. 
-- 
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


Re: First attempt at a Python prog (Chess)

2013-02-14 Thread jkn
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
 

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


Re: First attempt at a Python prog (Chess)

2013-02-14 Thread Ian Kelly
On Thu, Feb 14, 2013 at 10:48 AM, Chris Hinsley  wrote:
> Is a Python list as fast as a bytearray ? I didn't copy a C prog BTW !

>>> from timeit import Timer
>>> t1 = Timer("board[36] = board[20]; board[20] = ' '", "board = 
>>> bytearray('RNBQKBNR
>>> rnbqkbnr')")
>>> min(t1.repeat(10))
0.1678651895701826
>>> t2 = Timer("board[3][4] = board[1][4]; board[1][4] = ' '", "board = 
>>> [list('RNBQKBNR'), ['P'] * 8] + [[' ']*8 for i in range(4)] + [['p'] * 8, 
>>> list('rnbqkbnr')]")
>>> min(t2.repeat(10))
0.2080088391122672

Natively, it looks like the bytearray is about 19% faster for moving a
piece from one square to another.  Those array offsets aren't
calculated for free, though.  Look what happens when we have to do the
math:

>>> t3 = Timer("board[r1*8+c1] = board[r2*8+c2]; board[r2*8+c2] = ' '", "board 
>>> = bytearray('RNBQKBNR
>>> rnbqkbnr'); r1 = 3; r2 = 1; c1 = c2 = 4")
>>> min(t3.repeat(10))
0.314191887516472
>>> t4 = Timer("board[r1][c1] = board[r2][c2]; board[r2][c2] = ' '", "board = 
>>> [list('RNBQKBNR'), ['P'] * 8] + [[' ']*8 for i in range(4)] + [['p'] * 8, 
>>> list('rnbqkbnr')]; r1 = 3; r2 = 1; c1 = c2 = 4")
>>> min(t4.repeat(10))
0.24427881197186707

That said, the philosophy of Python focuses more on readability than
on speed.  The goalpost for speed in a Python program is that it be
"fast enough".  If you have more stringent speed requirements than
that, then Python may not be the right tool for the job.
-- 
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 06:05:13 +, Tim Roberts said:


Chris Hinsley  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-13 Thread Tim Roberts
Chris Hinsley  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 
-- 
Tim Roberts, t...@probo.com
Providenza & Boekelheide, Inc.
-- 
http://mail.python.org/mailman/listinfo/python-list


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  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


Re: First attempt at a Python prog (Chess)

2013-02-13 Thread Oscar Benjamin
On 13 February 2013 23:25, Chris Hinsley  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
-- 
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), \