I'm creating a python application to play the game Perudo (or Liar's dice).
I am trying to create a function that calculates all the possible moves that the player (or AI) is allowed to make and returns a list of them so that it can reject illegal ones.
Turns are stored as a list of 2 numbers e.g. [10,6] representing ten sixes.
If the starting variable currentbid is [19,3] (nineteen threes) and there are 20 dice in play, then the only possible moves are 19 fours, 19 fives, 19 sixes, 20 twos, 20 threes, 20 fours, 20 fives and 20 sixes. Calls of ones are not allowed.
The program should output the above as:
[[19,4],[19,5],[19,6],[20,2],[20,3],[20,4],[20,5],[20,6]]
but instead outputs it as:
[[20,6],[20,6],[20,6],[20,6],[20,6],[20,6],[20,6],[20,6]]
What am I doing wrong?
def calcpossiblemoves(self, currentbid, totalnoofdice):
self.possiblemoves = [] # Create a list of possible moves that will be added too
self.bid = currentbid
while self.bid[0] <= totalnoofdice:
while self.bid[1] < 6:
self.bid[1] += 1
self.possiblemoves.append(self.bid) # <- I think the problem is something to do with this line
print(self.possiblemoves) #For tracking the process
# Increase 1st number, reset 2nd number to 1
self.bid[0] += 1
self.bid[1] = 1 # Which will get increased to 2
#print("Reached 6")
return self.possiblemoves
The problem is that you are using lists, which are mutable objects, and you're creating references, rather than copies. You could fix it by copying the self.bid list each time, but the most "pythonic" solution is not to use list, but to use tuples, instead:
def calcpossiblemoves(self, currentbid, totalnoofdice):
possiblemoves = []
numberof, value = currentbid
while numberOf <= totalnoofdice:
while value < 6:
value += 1
possiblemoves.append((numberOf, value))
# Increase 1st number, reset 2nd number to 1
numberof += 1
value = 1 # Which will get increased to 2
#print("Reached 6")
return self.possiblemoves
Note that this doesn't update self.bid (but you can easily add that in), and you get a list of immutable tuples.
EDIT: Because tuples are immutable, I've used tuple unpacking to create two variables. This is to prevent the following problem:
>>> bid = (1, 2)
>>> bid[0] += 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
I could write bid = (bid[0]+1, bid[1]), but using two variables is, imho, easier to understand.
Generally, it's a good rule of thumb to make sure that all members of lists mean the same thing, whereas values meaning different things go in tuples or dicts, or custom containers such as NamedTuple or custom classes.
In this example, the outer list contains a number of bids, but each of the inner lists has a number of dice and a value, which indicates a list is perhaps the wrong type to use.
You're better off in thinking about a base 6 number here where you effectively have a range of numbers for 20 dice of 0 - 126 inclusive.
current_bid = [19, 3]
offset = current_bid[0] * 6 + current_bid[1]
# 117 - and divmod(117, 6) == (19, 3)
So, to then get the valid bids that are left, you do the maths over the range of 117 - 126 and get the number of dice and remainder that's valid.
valid_bids_with1s = ([n // 6, n % 6 + 1] for n in range(offset, 126))
valid_bids = [[a, b] for a, b in valid_bids_with1s if b != 1]
Which gives you:
[[19, 4],
[19, 5],
[19, 6],
[20, 2],
[20, 3],
[20, 4],
[20, 5],
[20, 6]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With