Touring a chess board with multiple pieces [Python] - python

I have been trying to solve this for 2 days straight and I just can't find a valid algorithm. Given a Chess board, and a number of pieces, I have to check if said board can be toured by the pieces, with the condition that each piece can only visit an square once. I know it's some kind of multiple backtracking, but I can't get it to work. (I only have been able to implement a general knight's tour for individual pieces)
tablero is a class of the board, that holds a name, a list of pieces, a list with prohibited positions, a list with the free positions, and a tuple with the dimensions of the board.
ficha is the class of a piece, it holds a name (nombre), a tuple with its position (posicion), a list with its valid movements (movimientos) (For example, a pawn's list would be [ [0,1] ], meaning it can only move forward 1)
Any insight is welcome.
Here are the classes (Feel free to add/remove any method).
def legal(pos,dimensiones):
if pos[0] >= 0 and pos[0] < dimensiones[0] and pos[1] >= 0 and pos[1] < dimensiones[0]:
return True
else:
return False
class board:
def __init__(self,name,pieces,dimention,prohibited_positions):
self.name = name
self.pieces = pieces
self.dimention = dimention
self.prohibited_positions = prohibited_positions
self.free_positions = []
for x in range(dimention[0]):
for y in range(dimention[1]):
self.free_positions.append([x,y])
for x,y in self.prohibited_positions:
if [x,y] in self.free_positions:
self.free_positions.remove([x,y])
for piece in self.pieces:
if self.piece.position in self.free_positions:
self.free_positions.remove(piece.position)
def append(self,piece):
pos = piece.position
if pos in self.free_positions:
self.pieces.append(piece)
self.free_positions.remove(pos)
class piece:
def __init__(self,name,position,move_offsets):
self.name=name
self.position=position
self.move_offsets=move_offsets
self.possible_movements=move_offsets
def setPos(self,pos):
self.position=pos
def ValidMovements(self,dim,free_positions,prohibited_positions):
aux = []
for i in self.possible_movements:
newX = self.position[0] + i[0]
newY = self.position[1] + i[1]
newPos = [newX,newY]
if legal(newPos,dim):
aux.append(newPos)
for i in list(aux):
if i not in free_positions:
aux.remove(i)

Related

Checked if the coordinates of a position are within a boundaries

I have created a function that is trying to figure out if the coordinates of a position are within the checkerboard boundaries (between 0 inclusive and the number
Below is my attempt:
def position_is_in_game(self, position):
# Replace self with a Game type object
one_game = Game()
#Replace position with an object of type Position
one_position = Position()
return one_game.position_is_in_game(one_position)
I feel my code is incomplete.
Assuming that your Position and Piece functions are coded correctly, the issue lies within the checking algorithm's syntax.
Try it like this:
def position_is_in_game(position_tuple):
game = Game()
game_positions = game.cases.keys()
for i in game_positions:
if i == position_tuple:
return True
else:
return False
Here is how I would check to see if a position in on the gird:
class Game :
def __init__(self):
self.n_lignes = 8
self.n_colonnes = 8
def position_is_in_game(self, x, y):
return x > 0 and x < self.n_lignes and y > 0 and y < self.n_colonnes
mygame = Game ()
print (mygame.position_is_in_game(1, 8))

Search for duplicates of items in list within list

Working on a basic project to simulate the life cycle of an organism using matplotlib. The organism's position is defined by list [x,y], and its position is randomly generated. Organism being the class
for i in range(numorganisms):
posX = random.randint(0,XMAX)
posY = random.randint(0,YMAX)
creatures.append(organism([posX,posY]))
There may be about 100 of these in the plot, meaning collisions will occur. I want to be able to search the list of creatures for instances where posX and posY are both equal, and then create a new list of those positions.
You may easily do this:
existing = set()
for i in range(numorganisms):
posX = random.randint(0,XMAX)
posY = random.randint(0,YMAX)
if (posX, posY) not in existing :
creatures.append(organism([posX,posY]))
existing.add( (posX, posY) )
else :
pass # do something else
This assumes you have some way to get the positions out of the instance of organism.
###############################
# This just recreates what I think you already have
import random
class organism:
def __init__(self, l):
self.l = l
XMAX = YMAX = 100
creatures = []
for i in range(100):
posX = random.randint(0,XMAX)
posY = random.randint(0,YMAX)
creatures.append(organism([posX,posY]))
print(creatures)
###############################
# Determine if there are redundancies
positions = [x.l for x in creatures]
print(positions)
collisions = [i for i in positions if positions.count(i) > 1]
print(collisions)

Issue with updating list in snake game

So I've been programming a snake game using python mode for processing, but I have been having an issue with the list I have set up for keeping track of the body of the snake itself.
My current implementation uses a list of vectors to keep track of the location of each segment of the snake. I then loop through this list to display the squares for each segment. At the beginning of the game, the list only has 1 entry (the head), but upon eating a piece of food, I insert a new vector to the front of the list with the same value as the current head. I then update the list but looping through it and finally, I update the head by using a velocity vector.
scl = 10
dim = 20
def setup():
global s
global f
size(dim * scl, dim * scl)
s = Snake()
f = Food()
def draw():
background(201)
global s
global f
if s.eat(f):
f.location()
s.update()
s.display()
f.display()
delay(50)
class Snake:
def __init__(self):
self.body = [PVector(0, 0)]
self.v = PVector(1, 0)
self.total = 1
def update(self):
for i in range(self.total - 1):
self.body[self.total - 1 - i] = self.body[self.total - 2 - i]
print("Position")
print(self.body)
self.body[0].x += self.v.x * scl
print(self.body)
self.body[0].y += self.v.y * scl
print(self.body)
def display(self):
fill(101)
for i in range(self.total):
rect(self.body[i].x + 1, self.body[i].y + 1, scl - 2, scl - 2)
def eat(self, p):
tmp = self.body[:]
dis = dist(self.body[0].x, self.body[0].y, p.pos.x, p.pos.y)
if dis < 1:
self.total += 1
self.body.insert(0, tmp[0])
return True
else:
return False
I expect the output to be a list of differing vectors, each that draw a square next to the previous and next entries. Instead, after eating food, all the vectors are the same within the body list. Does anyone know how I can fix this?
You seem to misunderstood, how python's list handles it's values.
tmp = self.body[:]
makes shallow copy, not deep copy. And:
self.body[...] = self.body[...]
doesn't copy the value. It just passes the value from one place, to another. So when you move your values in self.body by one offset, the first and the second element will end pointing to the same value.
Try something like this:
def update(self):
for i in range(self.total - 1):
self.body[self.total - 1 - i] = self.body[self.total - 2 - i]
print("Position")
print(self.body)
self.body[0] = PVector(self.body[0].x + self.v.x * scl, self.body[0].y + self.v.y * scl)
print(self.body)
and in eat function:
self.body.insert(0, PVector(tmp[0].x, tmp[0].y))

Python Negamax Algorithm

I have about as simple of a negamax algorithm as possible, for evaluating positions in Tic Tac Toe. The state of the game is stored as an array in numpy, with X's pieces represented by 1, and O's pieces represented by four.
I was testing this just now, and found:
a = np.zeros(9).reshape(3,3)
negaMax(a, 6, 1) # Returned zero as it should
negaMax(a, 7, 1) # Returns 100
Meaning that my algorithm thinks it has found a way for X to win in seven plies in a game of Tic Tac Toe, which is obviously impossible against decent play. I can't work out how to have it print the best moves it has found, so am having real trouble debugging this. What am I doing wrong?
def winCheck(state):
"""Takes a position, and returns the outcome of that game"""
# Sums which correspond to a line across a column
winNums = list(state.sum(axis=0))
# Sums which correspond to a line across a row
winNums.extend(list(state.sum(axis=1)))
# Sums which correspond to a line across the main diagonal
winNums.append(state.trace())
# Sums which correspond to a line across the off diagonal
winNums.append(np.flipud(state).trace())
if Square.m in winNums:
return 'X'
elif (Square.m**2 + Square.m) in winNums:
return 'O'
elif np.count_nonzero(state) == Square.m**2:
return 'D'
else:
return None
def moveFind(state):
"""Takes a position as an nparray and determines the legal moves"""
moveChoices = []
# Iterate over state, to determine which squares are empty
it = np.nditer(state, flags=['multi_index'])
while not it.finished:
if it[0] == 0:
moveChoices.append(it.multi_index)
it.iternext()
return moveChoices
def moveSim(state, move, player):
"""Create the state of the player having moved without interfering with the board"""
simState = state.copy()
if player == 1:
simState[move] = 1
else:
simState[move] = gamecfg.n + 1
return simState
def positionScore(state):
"""The game is either won or lost"""
if winCheck(state) == 'X':
return 100
elif winCheck(state) == 'O':
return -100
else:
return 0
def negaMax(state, depth, colour):
"""Recursively find the best move via a negamax search"""
if depth == 0:
return positionScore(state) * colour
highScore = -100
moveList = moveFind(state)
for move in moveList:
score = -negaMax(moveSim(state, move, colour), depth -1, colour * -1)
highScore = max(score, highScore)
return highScore
Your code does not consider the game to stop when a line of 3 symbols is made.
This means that it is playing a variant of tic-tac-toe where X wins if he makes a line of 3 even after O has made a line of 3.
For this variant, the program has correctly found that it is possible for X to always win!
(I came across the same situation with a chess program I made where the computer was happy to sacrifice its king if it would reach checkmate a little later...)

Quickly counting particles in grid

I've written some python code to calculate a certain quantity from a cosmological simulation. It does this by checking whether a particle in contained within a box of size 8,000^3, starting at the origin and advancing the box when all particles contained within it are found. As I am counting ~2 million particles altogether, and the total size of the simulation volume is 150,000^3, this is taking a long time.
I'll post my code below, does anybody have any suggestions on how to improve it?
Thanks in advance.
from __future__ import division
import numpy as np
def check_range(pos, i, j, k):
a = 0
if i <= pos[2] < i+8000:
if j <= pos[3] < j+8000:
if k <= pos[4] < k+8000:
a = 1
return a
def sigma8(data):
N = []
to_do = data
print 'Counting number of particles per cell...'
for k in range(0,150001,8000):
for j in range(0,150001,8000):
for i in range(0,150001,8000):
temp = []
n = []
for count in range(len(to_do)):
n.append(check_range(to_do[count],i,j,k))
to_do[count][1] = n[count]
if to_do[count][1] == 0:
temp.append(to_do[count])
#Only particles that have not been found are
# searched for again
to_do = temp
N.append(sum(n))
print 'Next row'
print 'Next slice, %i still to find' % len(to_do)
print 'Calculating sigma8...'
if not sum(N) == len(data):
return 'Error!\nN measured = {0}, total N = {1}'.format(sum(N), len(data))
else:
return 'sigma8 = %.4f, variance = %.4f, mean = %.4f' % (np.sqrt(sum((N-np.mean(N))**2)/len(N))/np.mean(N), np.var(N),np.mean(N))
I'll try to post some code, but my general idea is the following: create a Particle class that knows about the box that it lives in, which is calculated in the __init__. Each box should have a unique name, which might be the coordinate of the bottom left corner (or whatever you use to locate your boxes).
Get a new instance of the Particle class for each particle, then use a Counter (from the collections module).
Particle class looks something like:
# static consts - outside so that every instance of Particle doesn't take them along
# for the ride...
MAX_X = 150,000
X_STEP = 8000
# etc.
class Particle(object):
def __init__(self, data):
self.x = data[xvalue]
self.y = data[yvalue]
self.z = data[zvalue]
self.compute_box_label()
def compute_box_label(self):
import math
x_label = math.floor(self.x / X_STEP)
y_label = math.floor(self.y / Y_STEP)
z_label = math.floor(self.z / Z_STEP)
self.box_label = str(x_label) + '-' + str(y_label) + '-' + str(z_label)
Anyway, I imagine your sigma8 function might look like:
def sigma8(data):
import collections as col
particles = [Particle(x) for x in data]
boxes = col.Counter([x.box_label for x in particles])
counts = boxes.most_common()
#some other stuff
counts will be a list of tuples which map a box label to the number of particles in that box. (Here we're treating particles as indistinguishable.)
Using list comprehensions is much faster than using loops---I think the reason is that you're basically relying more on the underlying C, but I'm not the person to ask. Counter is (supposedly) highly-optimized as well.
Note: None of this code has been tested, so you shouldn't try the cut-and-paste-and-hope-it-works method here.

Categories