List index out of range in class - python

All code
import random
import time
class Enemy():
def __init__(self):
self.health = 100
self.power = random.randint(10,20)
def hit(self, player):
player.health -= self.power
class player():
def __init__(self):
self.health = 300
self.power = 50
def hit(self, Enemy):
Enemy.health -= self.power
player1 = player()
enemies = []
for i in range(5): # create 5 enemy
enemies.append(Enemy())
print("Play - Help - Quit")
action1 = input("Type 'hit' for enemies\n>>>> ")
while action1 != 'q':
print("---------------")
for i in range(len(enemies)):
print("#{}.enemy heatlh-->{}".format(i, enemies[i].health))
print("----------------")
random_enemy = random.randint(1, 5)
action = input(">>>> ")
if action == 'hit':
which = int(input("Which enemy? there are {} enemies\n>>>>".format(len(enemies))))
if enemies[which].health == 0:
enemies[which].health = 0
print("\nThis is a death enemy")
else:
player1.hit(enemies[which])
damage_enemy = random.randint(1,5)
if enemies[random_enemy].health == 0:
continue
else:
if damage_enemy == 1 or damage_enemy == 3 or damage_enemy == 4:
if enemies[which].health == 0 or enemies[which].health <= 0:
enemies[which].health = 0
print("{}. enemy death HP: {} ".format(which, enemies[which].health))
else:
enemies[random_enemy].hit(player1)
print("{}. enemy hit you {} damage, your HP: {} ".format(random_enemy,enemies[random_enemy].power,player1.health))
elif enemies[which].health != 0 or enemies[which].health >= 0:
print("{}. enemy HP: {} ".format(which, enemies[which].health))
elif action == 'q':
break
I get this error at random time, my list size is 5, enemies die and their healths are 0. They stay there, but for some reason sometimes I get this error.
#0.enemy heatlh-->100
#1.enemy heatlh-->100
#2.enemy heatlh-->0
#3.enemy heatlh-->0
#4.enemy heatlh-->100
if enemies[random_enemy].health == 0:
continue

The random.randint(1, 5) can return 5. Your list has 5 elements, but the indices are from 0 to 4.
P.S. Also, the minimum value that you get is 1. Not 0.

Related

How can I move around a list filled with class calls and when I'm on the class' indexspot how can I call it?

I've recently been trying to make a Textadventure but I'm having a big problem with the idea of "moving" around a List (x_achses) with a List inside(y-achses) it (my father called it a matrix) and in the second list (y-achses) there are a bunch of random types of things like an enemy. In that "Matrix" I wanna move around and on certain fields it should activate the assigned class(here it should simply print the classes name).
I've tried using the index of the list and changing dependently but it didn't work, I've tried using the len() function and changing it dependently but nothing ever seems to be happening. No classes or anything seem to be called. I have no idea what to do.
import random
import secrets
class Character:
def __init__(self, hp, ad, name):
self.hp = hp
self.ad = ad
self.name = name
def get_hit(self, ad):
self.hp = self.hp - ad
if self.hp <= 0:
self.die()
def is_dead(self):
return self.hp <= 0
def die(self):
print(self.name + " died")
class Human_enemies(Character):
def __init__(self):
super().__init__(self, 10, 3, "Mermaids")
Human_enemies.enemie_amount = random.randint(1, 9)
print("Mermaids")
def enemie_amount(self):
enemie_amount = random.randint(1, 9)
enemies = []
for i in range(enemie_amount):
enemies.append(Human_enemies())
class Vessel:
def __init__(self, hp, ad, storage, name):
self.hp = hp
self.ad = ad
self.storage = storage
self.name = name
def get_hit(self, ad):
self.hp = self.hp - ad
if self.hp <= 0:
self.die()
def is_dead(self):
return self.hp <= 0
def die(self):
print(self.name + " died")
class Sloop_ship(Vessel):
def __init__(self):
super().__init__(self, 1000, 50-100, 0, "Sloop")
def type(self):
print("Sloop")
class Brigattine_ship(Vessel):
def __init__(self):
super().__init__(self, 2500, 70-110, 15, "Brig")
def type(self):
print("Brig")
class Galleon_ship(Vessel):
def __init__(self):
super().__init__(self, 5000, 150-200, 40, "Galleon")
def type(self):
print("Galleon")
class Shipwreck:
def __init__(self):
print("Shipwreck")
wanna_loot = input("Do you want to check the wreck for any loot or survivors?\n")
#TODO: Make this better, sth. like chance of death or sth.
class Fields:
def Rougethingi(self):
random1 = random.randint(0, 5)
if random1 == 0:
return Shipwreck
elif random1 == 1:
return Human_enemies
elif random1 == 2:
return Sloop_ship
elif random1 == 3:
return Brigattine_ship
elif random1 == 4:
return Galleon_ship
else:
return None
class Map():
def __init__(self, x, y):
self.rowsX = []
self.x = x
self.y = y
for i in range(x):
self.rowsY = []
for r in range(y):
self.rowsY.append(Fields.Rougethingi(self))
self.rowsX.append(self.rowsY)
def print_map(self):
for j in self.rowsX:
print("")
for f in self.rowsY:
if f == None:
print("0 ", end = "")
elif f != None:
print("1 ", end = "")
print("\n")
class Player(Character):
def __init__(self):
super().__init__(self, 100, 1, player_name)
def start(self):
self.player_x = 1
self.player_y = 1
n.rowsX[self.player_x].__init__()
n.rowsY[self.player_y].__init__()
def move_right(self):
self.player_x = self.player_x + 1
if self.player_x >= n.x or self.player_x >= n.x - n.x:
print("You can't go further right")
def move_left(self):
self.player_x = self.player_x - 1
if self.player_x >= n.x or self.player_x >= n.x - n.x:
print("You can't go further right")
def move_up(self):
self.player_y = self.player_y + 1
if self.player_y >= n.y or self.player_y >= n.y - n.y:
print("You can't go further right")
def move_down(self):
self.player_y = self.player_y - 1
if self.player_y >= n.y or self.player_y >= n.y - n.y:
print("You can't go further right")
def quit_game():
exit("And the mighty adventurer decided to rest for the day...")
def print_help():
utility = print("(help, save, load, map,)")
movement = print("(forward, backwards, starboard, port)")
utility
movement
def save():
#TODO: Make a save system
pass
def load():
#TODO: Make a load system
pass
if __name__ == "__main__":
player_name = input("What is thy title scalywag?\n")
n = Map(30, 30)
m = Player.start
print("You shall call us for 'help' to help you with your role of Captain\n")
#? This is the main input loop --------------------------------------v
while True:
cmd = input(">>>")
if cmd == "help":
print_help()
continue
elif cmd == "map":
n.print_map()
continue
elif cmd == "quit":
quit_game()
elif cmd == "save":
save()
continue
elif cmd == "load":
load()
continue
elif cmd == "forward":
Player.move_up
continue
elif cmd == "backwards":
Player.move_down
continue
elif cmd == "starboard":
Player.move_right
continue
elif cmd == "port":
Player.move_left
continue
else:
print("I dont understand that... \n")
continue
#? This is the main input loop --------------------------------------v

python IndexError that I cannot resolve with dictionaries

I have a simple problem, and I need a pari of fresh eyes for this. I have a dictionary for my world:
world = {}
and a function that fills rooms in that dictionary based on a 2d array:
def makeRoomsForLevel():
counter = 1
for r in range(len(rooms)):
for c in range(len(rooms)):
if rooms[c][r] == 1:
world[f"room{counter}"] = Room(
f"room{counter}",
"",
{},
False,
None,
False,
None,
False,
None,
True,
(r, c)
)
counter += 1
And yet another function that I am working on to find the exits for the room:
def findExits():
counter = 1;
for x in range(len(world)):
if rooms[world[f"room{counter}"]].coords[0] + 1 == 1:
pass
I tried running this before I filled in the if statement, and it gave me this error:
IndexError: only integers, slices (':'), ellipsis ('...'), numpy.newaxis ('None') and integer or boolean arrays are valid indicies
I kinda know what it means, but it hasn't given me any problems with this before hand.
Here is the room class:
class Room():
def __init__(self, name, description, exits, hasWeapon, weapon, hasItem, item, hasEnemy, enemy, isFirstVisit, coords):
self.name = name
self.description = description
self.exits = exits
self.hasWeapon = hasWeapon
self.weapon = weapon
self.hasItem = hasItem
self.item = item
self.hasEnemy = hasEnemy
self.enemy = enemy
self.isFirstVisit = isFirstVisit
self.coords = coords
And here is what "rooms" is:
rooms = np.zeros((11, 11))
Here is the full generation code:
rooms = np.zeros((11, 11))
maxRooms = 7
possibleNextRoom = []
world = {}
def startLevel():
for r in range(len(rooms[0])):
for c in range(len(rooms[1])):
rooms[r][c] = 0
possibleNextRoom.clear()
halfHeight = int(len(rooms[1]) / 2)
halfWidth = int(len(rooms[0]) / 2)
rooms[halfWidth][halfHeight] = 1
def resetLevel():
for r in range(len(rooms[0])):
for c in range(len(rooms[1])):
rooms[r][c] = 0
possibleNextRoom.clear()
def countRooms():
roomCount = 0
for r in range(len(rooms)):
for c in range(len(rooms)):
if rooms[r][c] == 1:
roomCount += 1
return roomCount
def findPossibleRooms():
for r in range(len(rooms) - 1):
for c in range(len(rooms) - 1):
if rooms[r][c] == 1:
if rooms[r][c+1] != 1:
possibleNextRoom.append((r, c+1))
if rooms[r][c-1] != 1:
possibleNextRoom.append((r, c-1))
if rooms[r-1][c] != 1:
possibleNextRoom.append((r-1, c))
if rooms[r+1][c] != 1:
possibleNextRoom.append((r+1, c))
def addRoom():
x = random.randrange(0, len(possibleNextRoom))
rooms[possibleNextRoom[x][0]][possibleNextRoom[x][1]] = 1
possibleNextRoom.pop(x)
def generateLevel():
global x, possibleNextRoom
startLevel()
while countRooms() < maxRooms:
countRooms()
findPossibleRooms()
addRoom()
def makeRoomsForLevel():
counter = 1
for r in range(len(rooms)):
for c in range(len(rooms)):
if rooms[c][r] == 1:
world[f"room{counter}"] = Room(
f"room{counter}",
"",
{},
False,
None,
False,
None,
False,
None,
True,
(r, c)
)
counter += 1
def findExits():
counter = 1;
for x in range(len(world)):
if rooms[world[f"room{counter}"].coords[0]] + 1 == 1:
pass
def fillRooms():
counter = 1
for x in range(len(world)):
x = random.randrange(1, 2)
if x == 1:
world[f"room{counter}"].hasItem = True
x = random.randrange(1, 10)
if x == 1:
world[f"room{counter}"].hasWeapon = True
x = random.randrange(1, 4)
if x == 1:
world[f"room{counter}"].hasEnemy = True
counter += 1
And here is the entire code:
import random
import numpy as np
world = {}
class Player():
def __init__(self, health, maxHealth, baseDmg, dmg, name, weapons, items, isAlive, previousRoom, roomName):
self.health = health
self.maxHealth = maxHealth
self.baseDmg = baseDmg
self.dmg = dmg
self.name = name
self.weapons = weapons
self.items = items
self.isAlive = isAlive
self.previousRoom = previousRoom
self.room = world[roomName]
def Move(self, direction):
if direction not in self.room.exits:
print("Cannot Move In That Direction!")
return
newRoomName = self.room.exits[direction]
self.previousRoom = world[self.room.name]
print("Moving to", newRoomName)
self.room = world[newRoomName]
def MoveBack(self):
self.room = world[self.previousRoom.name]
print("Moving to", self.room.name)
class Enemy():
def __init__(self, health, dmg, hasLoot, lootItem, isAlive):
self.health = health
self.dmg = dmg
self.hasLoot = hasLoot
self.lootItem = lootItem
self.isAlive = isAlive
class Weapon():
def __init__(self, name, dmg, description):
self.name = name
self.dmg = dmg
self.description = description
class Item():
def __init__(self, name, amt, description):
self.name = name
self.amt = amt
self.description = description
class Room():
def __init__(self, name, description, exits, hasWeapon, weapon, hasItem, item, hasEnemy, enemy, isFirstVisit, coords):
self.name = name
self.description = description
self.exits = exits
self.hasWeapon = hasWeapon
self.weapon = weapon
self.hasItem = hasItem
self.item = item
self.hasEnemy = hasEnemy
self.enemy = enemy
self.isFirstVisit = isFirstVisit
self.coords = coords
#######################Dungeon Generation###################
rooms = np.zeros((11, 11))
maxRooms = 7
possibleNextRoom = []
def startLevel():
for r in range(len(rooms[0])):
for c in range(len(rooms[1])):
rooms[r][c] = 0
possibleNextRoom.clear()
halfHeight = int(len(rooms[1]) / 2)
halfWidth = int(len(rooms[0]) / 2)
rooms[halfWidth][halfHeight] = 1
def resetLevel():
for r in range(len(rooms[0])):
for c in range(len(rooms[1])):
rooms[r][c] = 0
possibleNextRoom.clear()
def countRooms():
roomCount = 0
for r in range(len(rooms)):
for c in range(len(rooms)):
if rooms[r][c] == 1:
roomCount += 1
return roomCount
def findPossibleRooms():
for r in range(len(rooms) - 1):
for c in range(len(rooms) - 1):
if rooms[r][c] == 1:
if rooms[r][c+1] != 1:
possibleNextRoom.append((r, c+1))
if rooms[r][c-1] != 1:
possibleNextRoom.append((r, c-1))
if rooms[r-1][c] != 1:
possibleNextRoom.append((r-1, c))
if rooms[r+1][c] != 1:
possibleNextRoom.append((r+1, c))
def addRoom():
x = random.randrange(0, len(possibleNextRoom))
rooms[possibleNextRoom[x][0]][possibleNextRoom[x][1]] = 1
possibleNextRoom.pop(x)
def generateLevel():
global x, possibleNextRoom
startLevel()
while countRooms() < maxRooms:
countRooms()
findPossibleRooms()
addRoom()
def makeRoomsForLevel():
counter = 1
for r in range(len(rooms)):
for c in range(len(rooms)):
if rooms[c][r] == 1:
world[f"room{counter}"] = Room(
f"room{counter}",
"",
{},
False,
None,
False,
None,
False,
None,
True,
(r, c)
)
counter += 1
def findExits():
counter = 1;
for x in range(len(world)):
if rooms[world[f"room{counter}"].coords[0]] + 1 == 1:
pass
def fillRooms():
counter = 1
for x in range(len(world)):
x = random.randrange(1, 2)
if x == 1:
world[f"room{counter}"].hasItem = True
x = random.randrange(1, 10)
if x == 1:
world[f"room{counter}"].hasWeapon = True
x = random.randrange(1, 4)
if x == 1:
world[f"room{counter}"].hasEnemy = True
counter += 1
############################################################
generateLevel()
makeRoomsForLevel()
findExits()
WoodenSword = Weapon("Wooden Sword", 5, "A wooden sword. Looks like a kid's toy.")
IronDagger = Weapon("Iron Dagger", 8, "Small, sharp, and pointy. Good for fighting monsters!")
HealthPot = Item("Health Potion", 1, "A Potion of Instant Health. Restores 10 Health.")
goblin1 = Enemy(25, 2, True, [HealthPot, IronDagger], True)
player = Player(10, 10, 5, 5, "", [], [], True, "room1", "room1")
def ShowInv():
print("*******************************")
print("Name:", player.name)
print("Health:", player.health)
print("Weapons:")
for i in player.weapons:
print(" ===============================")
print(" Weapon:", i.name)
print(" Description:", i.description)
print(" Damage:", i.dmg)
print(" ===============================")
print("Items:")
for i in player.items:
print(" ===============================")
print(" Item:", i.name)
print(" Amount:", i.amt)
print(" Description:", i.description)
print(" ===============================")
print("*******************************")
def testItems(item):
exists = item in player.items
return exists
def fight(enemy):
print("Your Health:", player.health)
print("Enemy Health:", enemy.health)
ans = input("What would you like to do?\n>>")
if ans == "attack":
chance = random.randrange(1, 20)
if chance >= 10:
enemy.health -= player.dmg
else:
print("You did not roll high enough...\nYour turn has been passed...")
if ans == "heal":
chance = random.randrange(1, 20)
if testItems(HealthPot):
if chance >= 10:
x = 0
for item in player.items:
if item == HealthPot:
player.health += 10
if player.health > player.maxHealth:
player.health = player.maxHealth
item.amt -= 1
if item.amt <= 0:
player.items.pop(x)
break
x += 1
else:
print("You did not roll high enough...\nYour turn has been passed...")
if ans == "run":
chance = random.randrange(1, 20)
if chance >= 10:
player.MoveBack()
else:
print("You did not roll high enough...\nYour turn has been passed...")
if enemy.health > 0 and player.health > 0:
chance = random.randrange(1, 20)
if chance >= 10:
player.health -= enemy.dmg
else:
if enemy.health <= 0:
enemy.isAvile = False;
def testRoom():
if player.room.hasWeapon:
if player.room.isFirstVisit:
player.weapons.append(player.room.weapon)
if player.room.hasItem:
if player.room.isFirstVisit:
player.items.append(player.room.item)
if player.room.hasEnemy:
if player.room.isFirstVisit:
while player.room.enemy.health > 0:
fight(player.room.enemy)
player.room.isFirstVisit = False
while True:
command = input(">>")
if command in {"N", "S", "E", "W"}:
player.Move(command)
testRoom()
elif command == "look":
print(player.room.description)
print("Exits:", *','.join(list(player.room.exits.keys())))
elif command == "inv":
ShowInv()
elif command == "heal":
if testItems(HealthPot):
player.health += 10
if player.health > player.maxHealth:
player.health = player.maxHealth
else:
print("You don't have any", HealthPot.name, "\bs")
else:
print("Invalid Command")
IIUC, you need something like:
#find the name of the room given the coordinates
def findRoom(x, y):
for i in range(len(world)):
if world[f"room{i+1}"].coords == (x, y):
return f"room{i+1}"
return None
def findExits():
for i in range(len(world)):
x, y = world[f"room{i+1}"].coords
exits = dict()
#east
if rooms[x, y+1] == 1:
exits["E"] = findRoom(x, y+1)
#south
if rooms[x+1, y] == 1:
exits["S"] = findRoom(x+1, y)
#west
if rooms[x, y-1] == 1:
exits["W"] = findRoom(x, y-1)
#north
if rooms[x-1, y] == 1:
exits["N"] = findRoom(x-1, y)
world[f"room{i+1}"].exits = exits
After running the above, the exits for room1 look like:
>>> world["room1"].exits
{'E': 'room2', 'S': 'room4'}
You can work with the above structure, changing the keys and values as needed.

Creating the war(card) game using OOP in Python

I am trying to create the war card game where 2 players draw a card each on the table, and the player whose card has max value gets both the cards, if the card values are equal(called war condition) each player draws 5 cards, and the value of the last card among these 5 cards are compared and works similarly as above. A player wins when either the other player runs out of cards or if in war condition the other player has less than 5 cards.
My questions:
When I am running the game logic sometimes it runs but sometimes it gets stuck in an infinite loop. Why?
I can notice that when the total number of cards for both players at all times should be 52, but here it is decreasing. Why? (I can see that the cards are getting lost every time the game goes into war condition, but I am not able to understand why that is happening, since I am adding all the 10 cards to the player whose card has a greater value.)
I have tried another method where I assume that players are always at war and then approach it, which works. But I want to understand why, if I break it into steps which I am trying to do here, is it not working?
Code:
import random
suits = ['Hearts','Clubs','Spades','Diamonds']
ranks = ['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace']
values = {'Two': 2, 'Three': 3, 'Four': 4, 'Five': 5, 'Six' : 6 , 'Seven' :7, 'Eight': 8,'Nine':9,
'Ten':10,'Jack':11, 'Queen': 12,'King': 13,'Ace':14 }
classes:
class Card():
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
self.value = values[rank]
#string method
def __str__(self):
return self.rank + ' of ' + self.suit
class Deck():
def __init__(self):
self.all_cards = [] #list of objects
for suit in suits:
for rank in ranks:
#create card object
created_card = Card(suit,rank)
self.all_cards.append(created_card)
def shuffle(self): #method to shuffle the card
random.shuffle(self.all_cards)
def deal_one(self):
return self.all_cards.pop() #we want the last card from deck
class Player():
def __init__(self,name):
self.name = name
self.all_cards = []
def remove_one(self):
return self.all_cards.pop(0) #to remove card from beginning of the list
def add_cards(self,new_cards):
if type(new_cards) == type([]):
self.all_cards.extend(new_cards)
else:
self.all_cards.append(new_cards)
def __str__(self):
return f'Player {self.name} has {len(self.all_cards)} cards.'
And below is the final game logic:
#create 2 new instances of the player class
player1_name = input('Enter the name of Player1: ')
player2_name = input('Enter the name of Player2: ')
player1 = Player(player1_name)
player2 = Player(player2_name)
newdeck = Deck()
newdeck.shuffle()
#splitting the deck among the two players - alternate card from deck goes to each player respectively
for i in range(0,len(newdeck.all_cards)-1,2):
player1.add_cards(newdeck.all_cards[i])
player2.add_cards(newdeck.all_cards[i+1])
#for x in range(26):
# player1.add_cards(newdeck.deal_one())
#player2.add_cards(newdeck.deal_one())
print(player1)
print(player2)
game_status = True
round_num = 0
while game_status == True:
round_num +=1
print(f"Round {round_num}")
if len(player1.all_cards) == 0:
print('Player 1 out of cards'+ player2.name + 'Wins!')
game_status = False
break
if len(player2.all_cards) == 0:
print('Player 2 out of cards' + player1.name + 'Wins!')
game_status = False
break
else:
player_cards = []
player1_card = player1.remove_one()
player2_card = player2.remove_one()
player_cards.append(player1_card)
player_cards.append(player2_card)
print('player1_card_value: ',player1_card.value)
print('')
print('player2_card_value: ',player2_card.value)
print('')
print(player1)
print('')
print(player2)
at_war = True
if player1_card.value == player2_card.value:
while at_war == True:
player1_list = []
player2_list = []
card_list = []
if len(player1.all_cards) < 5:
print('Player 2 won')
game_status = False
at_war = False
break
elif len(player2.all_cards) <5:
print('Player 1 won')
game_status = False
at_war = False
break
if len(player1.all_cards) >= 5 and len(player2.all_cards) >= 5:
for i in range(5):
player1_list.append(player1.remove_one())
player2_list.append(player2.remove_one())
card_list.extend(player1_list)
card_list.extend(player2_list)
print("CARD LIST LEN", len(card_list))
if player1_list[0].value > player2_list[0].value:
player1.add_cards(card_list)
at_war = False
break
elif player1_list[0].value < player2_list[0].value:
player2.add_cards(card_list)
#player2.add_cards(player1_list)
at_war = False
break
else:
at_war = True
elif player1_card.value > player2_card.value:
player1.add_cards(player_cards)
#player1.add_cards(player2_cards)
#print('p1>p2', player1)
elif player2_card.value > player1_card.value:
player2.add_cards(player_cards)
print(player1)
print(player2)
if len(player1.all_cards) == 0:
print('Player 2 won')
elif len(player2.all_cards) == 0:
print('Player 1 won')
Output: When it was stuck in an infinite loop:(You can see the total number of cards is now 34 instead of 52.)

Connect 4 implemented with python AI alpha-beta-pruning (Recursion/MemoryError)?

I'm trying to create a game called Connect Four with AI which uses the alpha-beta pruning algorithm in python. Here is the code I have managed to write:
# -*- coding: utf-8 -*-
import sys
class ConnectFour:
def __init__(self):
self.board = [[],[],[],[],[],[]]
for i in range(7):
for j in range(6):
self.board[j].append(" ")
self.moves = 0
self.colstack = [0,0,0,0,0,0,0]
self.node = 0
self.move = 0
def PrintGameBoard(self):
print(' 0 1 2 3 4 5 6')
for i in range(5, -1, -1):
print('|---|---|---|---|---|---|---|')
print("| ",end="")
for j in range(7):
print(self.board[i][j],end="")
if j != 6:
print(" | ",end="")
else:
print(" |")
print('`---------------------------ยด')
def CanPlay(self, col):
return self.colstack[col] < 6
def Play(self, col, board):
board[self.colstack[col]][col] = 2
self.colstack[col] += 1
self.moves += 1
return board
def IsWinning(self, currentplayer):
for i in range(6):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i][j+1] == currentplayer and self.board[i][j+2] == currentplayer and self.board[i][j+3] == currentplayer:
return True
for i in range(3):
for j in range(7):
if self.board[i][j] == currentplayer and self.board[i+1][j] == currentplayer and self.board[i+2][j] == currentplayer and self.board[i+3][j] == currentplayer:
return True
for i in range(3):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i+1][j+1] == currentplayer and self.board[i+2][j+2] == currentplayer and self.board[i+3][j+3] == currentplayer:
return True
for i in range(3,6):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i-1][j+1] == currentplayer and self.board[i-2][j+2] == currentplayer and self.board[i-3][j+3] == currentplayer:
return True
return False
def AlphaBeta(self, alpha, beta):
self.node += 1
if self.moves == 42:
return 0
for col in range(7):
if self.CanPlay(col) and self.IsWinning(2):
return (43 - self.moves)/2
max = (41 - self.moves)/2
if beta > max:
beta = max
if alpha >= beta:
return beta
for col in range(7):
if self.CanPlay(col):
self.board[self.colstack[col]][col] = 2
self.move = col
score = -self.AlphaBeta(-alpha, -beta)
if score >= beta:
return score
elif score > alpha:
alpha = score
self.board[self.colstack[col]][col] = " "
def Solve(self, table, week=False):
self.node = 0
self.board = table
if week:
self.AlphaBeta(-1, 1)
self.board = self.Play(self.move, table)
return self.board
else:
self.AlphaBeta(-21, 21)
self.board = self.Play(self.move, table)
return self.board
def PlayerMove(self, table):
self.board = table
try:
allowedmove = False
while not allowedmove:
print("Choose a column where you want to make your move (0-6): ",end="")
col =input()
if self.CanPlay(int(col)):
self.board[self.colstack[int(col)]][int(col)] = 1
self.moves += 1
self.colstack[int(col)] += 1
allowedmove = True
else:
print("This column is full")
except (NameError, ValueError, IndexError, TypeError, SyntaxError) as e:
print("Give a number as an integer between 0-6!")
else:
return self.board
def PlayerMark():
print("Player 1 starts the game")
mark = ''
while not (mark == "1" or mark == "2"):
print('Do you want to be 1 or 2: ',end="")
mark = input()
if mark == "1":
return 1
else:
return 2
def PlayAgain():
print('Do you want to play again? (yes or no) :',end="")
return input().lower().startswith('y')
def main():
sys.setrecursionlimit(2000)
print("Connect4")
while True:
mark = PlayerMark()
connectfour = ConnectFour()
if mark==1:
print("You are going to start the game\r\n\r\n")
else:
print("Computer (negamax) starts the game")
gameisgoing = True
table = [[],[],[],[],[],[]]
for i in range(7):
for j in range(6):
table[j].append(" ")
while gameisgoing:
connectfour.PrintGameBoard()
if mark == 1:
table = connectfour.PlayerMove(table)
if connectfour.IsWinning(1):
connectfour.PrintGameBoard()
print('You won the game!')
gameisgoing = False
else:
if connectfour.moves==42:
connectfour.PrintGameBoard()
print('Game is tie')
break
else:
mark = 2
else:
move = connectfour.Solve(table)
if connectfour.IsWinning(2):
connectfour.PrintGameBoard()
print('Computer won the game')
gameisgoing = False
else:
if connectfour.moves==42:
connectfour.PrintGameBoard()
print('Game is tie')
break
else:
mark = 1
if not PlayAgain():
print("Game ended")
break
if __name__ == '__main__':
main()
I'm not sure if the algorithm is working properly, but the problem is that I get RecursionError: maximum recursion depth exceeded in comparison. If I increase recursionlimit I get in around 10000 MemoryError: Stack Overflow. I think that the problem is that there is too many states to handle for my computer. That's why I changed the negamax algorithm to alpha-beta pruning, but there seem to be still to many states. Is there a effective technique that does algorithmic search, for example max depth 10 and still the computer is almost invincible? I'm waiting your solutions.

Why doesn't the main while loop finish executing? It just hangs up somewhere

We are making this Black Jack program to test card counting methods. We are trying to get the auto play function working, and it does, but when we run it in a while loop the loop never finishes and exits.
"""
Eli Byers
Josh Rondash
Black_Jack.py
"""
import random
#---------- CLASSES -----------------------------------------------------------
class Card(object):
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
self.value = 0
if self.rank is "Ace":
self.value = 11
if self.rank.isdigit():
self.value = int(self.rank)
if self.rank in ["Jack", "Queen", "King"]:
self.value = 10
def __str__(self):
return "["+str(self.rank)+" "+str(self.suit)+"]"
class Deck(object):
def __init__(self, numofdecks):
self.deck = []
self.suit = [" Clubs", " Hearts", " Spades", " Diamonds"]
self.rank = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"]
self.numofdecks = numofdecks
for i in range(self.numofdecks):
for r in self.rank:
for s in self.suit:
self.deck.append(Card(r,s))
def __str__(self):
deck_str = ""
for card in self.deck:
deck_str += str(card)+" "
deck_str = deck_str[:-1]
return deck_str
def __len__(self):
return len(self.deck)
def __getitem__(self,i):
return self.deck[i]
def __delitem__(self, i):
del self.deck[i]
def draw(self):
top_card = self.deck[0]
del self.deck[0]
return top_card
def addcard(self,card):
self.deck.append(card)
def shuffle(self): #Random shuffle function
a = len(self.deck)
b = a-1
for d in range(b,0,-1):
e = random.randint(0,d)
if e == d:
continue
self.deck[d],self.deck[e] = self.deck[e],self.deck[d]
return self.deck
class Player(object):
def __init__(self, bankroll):
self.hand = []
self.bankroll = bankroll
self.score = 0
self.bet = 0
self.count = 0
self.aces = 0
self.dealer_hand = []
def __str__(self):
hand = ""
for card in self.hand:
hand += str(card)+" "
return "Hand: "+hand+" Bank: "+str(self.bankroll)+" Bet: "+str(self.bet)+" Ct: "+str(self.count)+" A: "+str(self.aces)
def __getitem__(self, i):
return self.hand[i]
def getcard(self,Card):
self.hand.append(Card)
self.score = 0
ace = 0
for card in self.hand:
if card.rank == "Ace":
ace += 1
self.score += 1
else:
self.score += card.value
for a in range(ace):
if (self.score + 10) <= 21:
self.score += 10
self.updateCount(Card,"P")
def placebet(self, b=0):
if b != 0:
self.bankroll -= b
self.bet += b
else:
self.bet += input("Bankroll: "+str(self.bankroll)+" Ct: "+str(self.count)+" A: "+str(self.aces)+" Place bet: ")
self.bankroll -= self.bet
def updateCount(self, card, player):
if card.value in range(2,6):
self.count += 1
elif card.value is 10:
self.count -= 1
elif card.rank is "Ace":
self.aces += 1
if player == "D":
self.dealer_hand.append(card)
def makeBet(self):
bet = 0.1*self.bankroll
if self.count > 3:
c = 0
for i in range(self.count):
c += 1
if c == 3:
bet += 0.5 * bet
c = 0
elif self.count < -3:
bet -= 0.5 * bet
return bet
def Play(self):
if self.score < 17:
choice = 1 #hit
else:
choice = 2 #stand
return choice
class Dealer(object):
def __init__(self, Deck, discardpile, Player):
self.deck = Deck
self.discardpile = discardpile
self.player = Player
self.hand = []
self.score = 0
def __str__(self):
hand = ""
for card in self.hand:
hand += str(card)+" "
return "Dealer Hand: "+hand
def __getitem__(self, i):
return self.deck[i]
def draw(self):
cardval = self.deck.draw()
self.hand.append(cardval)
self.score = 0
ace = 0
for card in self.hand:
if card.rank == "Ace":
ace += 1
self.score += 1
else:
self.score += card.value
for a in range(ace):
if (self.score + 10) <= 21:
self.score += 10
player.updateCount(cardval,"D")
def deal(self, Player):
for i in range(2):
self.player.getcard(self.deck.draw())
self.draw()
def burn(self):
self.discardpile.addcard(self.deck.draw())
def blackjack(self):
if self.score == 21:
return True
else:
return False
class Table(Dealer, Player):
def __init__(self, Dealer, Player, Deck , discardpile):
self.dealer = Dealer
self.player = Player
self.deck = Deck
self.discardpile = discardpile
self.betplaced = 0
def initGame(self):
self.clearTable()
Deck.shuffle(self.deck)
self.dealer.burn()
def clearTable(self):
for card in self.player.hand:
self.discardpile.addcard(card)
for card in self.dealer.hand:
self.discardpile.addcard(card)
self.player.hand = []
self.dealer.hand = []
def playGame(self):
self.betplaced = self.player.placebet()
self.dealer.deal(self.player)
print self.player
print self.dealer
if self.dealer.blackjack():
print("Dealer Black Jack!")
elif self.player.score <= 21:
stand = 0
while self.player.score < 21 and stand == 0:
print("Use number Keys> Hit: 1 Stand: 2")
choice = input()
if choice == 1: # Hit
self.player.getcard(self.deck.draw())
elif choice == 2: # Stand
stand = 1
print self.player
print ("Your score is "+str(self.player.score))
while self.dealer.score <= 17 and self.player.score <= 21:
if self.dealer.score == 17:
for card in self.dealer.hand:
if card.rank == "Ace":
self.dealer.draw()
else:
self.dealer.draw()
print self.dealer
print ("Dealer score is "+str(self.dealer.score))
if self.dealer.score <= 21:
if (self.player.score > self.dealer.score) and (self.player.score <= 21) :
if self.player.score == 21:
self.player.bankroll += self.player.bet*2.5
else:
self.player.bankroll += self.player.bet*2
print ("Win")
elif self.player.score == self.dealer.score:
self.player.bankroll += self.player.bet
print("Push")
else:
print("You Lose")
elif (self.dealer.score > 21) and (self.player.score <= 21):
if self.player.score == 21:
self.player.bankroll += self.player.bet*2.5
else:
self.player.bankroll += self.player.bet*2
print ("Win")
else:
print("You Lose.")
self.player.bet = 0
self.player.dealer_hand = []
print
def autoPlay(self):
self.betplaced = self.player.placebet(int(self.player.makeBet()))
self.dealer.deal(self.player)
if (self.dealer.blackjack() == False) and (self.player.score <= 21):
stand = 0
while self.player.score < 21 and stand == 0:
choice = player.Play()
if choice == 1: # Hit
self.player.getcard(self.deck.draw())
elif choice == 2: # Stand
stand = 1
while self.dealer.score <= 17 and self.player.score <= 21:
if self.dealer.score == 17:
for card in self.dealer.hand:
if card.rank == "Ace":
self.dealer.draw()
else:
self.dealer.draw()
if self.dealer.score <= 21:
if (self.player.score > self.dealer.score) and (self.player.score <= 21):
if self.player.score == 21:
self.player.bankroll += self.player.bet*2.5
else:
self.player.bankroll += self.player.bet*2
print ("Win")
elif self.player.score == self.dealer.score:
self.player.bankroll += self.player.bet
print("Push")
else:
print("Lose")
elif (self.dealer.score > 21) and (self.player.score <= 21):
if self.player.score == 21:
self.player.bankroll += self.player.bet*2.5
else:
self.player.bankroll += self.player.bet*2
print ("Win")
else:
print("Lose")
self.player.bet = 0
self.player.dealer_hand = []
print self.player.bankroll
#----------- MAIN -----------------------------------
deck = Deck(6)
player = Player(500)
discardpile = Deck(0)
dealer = Dealer(deck, discardpile, player)
table = Table(dealer, player, deck, discardpile)
table.initGame()
while (player.bankroll > 0) and (player.bankroll < 1000):
table.autoPlay()
table.clearTable()
print "Game Over."
Just add some debug statements. You have multiple while loops in your methods. I'm sure a simple print statement will catch the errors in your logic.
DUDE, I found the infinite loop within 1 minute. lucky i had python installed on my box.
LINE 251
if (self.dealer.blackjack() == False) and (self.player.score <= 21):
stand = 0
while self.player.score < 21 and stand == 0:
print "in player score"
choice = player.Play()
if choice == 1: # Hit
self.player.getcard(self.deck.draw())
elif choice == 2: # Stand
stand = 1
while self.dealer.score <= 17 and self.player.score <= 21:
print "in dealer score"
print self.dealer.score
if self.dealer.score == 17:
for card in self.dealer.hand:
if card.rank == "Ace":
self.dealer.draw()
else:
self.dealer.draw()

Categories