User:Integer/uno.py

import os import sys import random import math import time

class BadInputError(Exception): pass

class Player:

def __init__(self, name): self.id = None self.name = name self.type = 'Human' self.hand = Hand self.legalCards = [] self.wildCards = [] self.valueChangeCards = [] self.zeroCards = [] self.canSkip = False self.canReverse = False self.canDrawTwo = False self.canDrawFour = False self.canValueChange = False self.drew = False self.scrollMax = 0 self.points = 0 self.forceDraw = 0

def addCard(self, card): self.drew = True if self.forceDraw > 0: self.forceDraw -= 1 self.drew = False self.hand.addCard(card) def beginTurn(self): self.drew = False def didDraw(self): return self.drew def getLegalCards(self, color, value, zeroChange=False): self.canSkip = False self.canReverse = False self.canDrawTwo = False self.canDrawFour = False self.canValueChange = False self.canZeroChange = False self.legalCards = [] self.wildCards = [] self.valueChangeCards = [] self.zeroCards = [] plusFours = [] for card in self.hand: if card.isWild: if card.getValue == '+4': plusFours.append(card) else: self.wildCards.append(card) elif zeroChange and card.isZero: self.canZero = True self.zeroCards.append(card) elif card.getColor == color or card.getValue == value: if card.getColor != color: self.canValueChange = True self.valueChangeCards.append(card) if card.getValue == "+2": self.canDrawTwo = True elif card.getValue == 'R': self.canReverse = True elif card.getValue == 'X': self.canSkip = True self.legalCards.append(card) if len(self.legalCards) == 0 and len(plusFours) > 0: self.canDrawFour = True self.wildCards += plusFours def getValidCards(self): return self.legalCards def getAllValidCards(self): return self.legalCards + self.wildCards + self.zeroCards def hasLegalCard(self): return len(self.legalCards) > 0 def addPoints(self, amount): if (self.points + amount) <= 999999999999999999999: self.points += amount def removeCard(self, index): return self.hand.removeCard(index) def assignID(self, identity): self.id = identity

def getName(self): return self.name

def getID(self): return self.id   def getPoints(self): return self.points

def getType(self): return self.type

def getCardNum(self): return len(self.hand)

def getHand(self, scrollNum=0, hide=False): return self.hand.show(scrollNum, hide) def getForceDraws(self): return self.forceDraw def addForceDraw(self, num): self.forceDraw += num def decreaseForceDraw(self): self.forceDraw -= 1 def removeForceDraw(self): self.forceDraw = 0

def checkCard(self, index): return self.hand.getCard(int(index)) def discardHand(self): self.hand.discard def __str__(self): return self.name def __repr__(self): return '({},{})'.format(self.name, self.points)

class Hand: deck' (Deck) : Card's Color (rgby) 'numberOfCards' (int) : Card's Value (0-9, R, X, W, +2, +4)'''

def __init__(self, deck=None,numberOfCards=0): self.hand = [] if deck != None: self.draw(deck,numberOfCards)

def __iter__(self): return iter(self.hand)

def __len__(self): return len(self.hand)

def __getitem__(self, item): try: return self.hand[item] except: return ''

def addCard(self, card): self.hand.append(card) def removeCard(self, index): index = int(index) if (0 <= index < len(self)): return self.hand.pop(index)

def discard(self): self.hand = []

def show(self, scrollNum=0, hide=False): if scrollNum == -1: scrollNum = 0 output = '' num = 0 header, footer, upper, lower = , , ,  header +=  ('\033[97m\u2666--\u2666\033[0m ') upper +=   ('\033[97m|<-|\033[0m ') lower +=   ('\033[97m|<-|\033[0m ') footer +=  ('\033[97m\u2666--\u2666\033[0m ') for i in range(10): indexNum = i+(10*scrollNum) if indexNum < len(self): header += (self[indexNum].getRow(0,hide)+' ') upper += (self[indexNum].getRow(1,hide)+' ') lower += (self[indexNum].getRow(2,hide)+' ') footer += (self[indexNum].getRow(3,hide)+' ') num += 1 for j in range(10-num): j #unused header += ('    ') footer += ('    ') upper += ('    ') lower += ('    ') header +=  ('\033[97m\u2666--\u2666\033[0m ') upper +=   ('\033[97m|->|\033[0m ') lower +=   ('\033[97m|->|\033[0m ') footer +=  ('\033[97m\u2666--\u2666\033[0m ') output += (' '+header+'\n  '+upper+'\n  '+lower+'\n  '+footer+'\n\033[97m|-(<)--') for k in range(num): output += '({})'.format(k) output += '--' for l in range(10-num): l #unused output += '-' output += '(>)--|\033[0m\n' return output

def getCard(self, index): return self.hand[index] def indexCard(self, card): return self.hand.index(card)

class GameSettings: playerIdentities = ('play1','play2','play3','play4') computerNames = ('Watson','SkyNet','Hal','Metal Gear') def __init__(self): self.playerStaging = []                 #    Where Player Objs Are Stored Before Game Starts self.players = {}                       #    ID : Player Obj self.numPlayers = 0 self.useColor = True self.displayEffects = True self.hideComputerHands = True self.zeroChange = False self.computerSimulation = False self.mainMenuError = '' self.computerSpeed = 'normal' def canAddPlayer(self): return (self.numPlayers < 4) def canRemovePlayer(self): return (self.numPlayers > 0) def canBegin(self): return (self.numPlayers > 1) def addPlayer(self, player): self.playerStaging.append(player) self.numPlayers += 1 def removePlayer(self, number): number -= 1 del self.playerStaging[number] self.numPlayers -= 1 def clearStaging(self): self.numPlayers = 0 self.playerStaging = [] def finalizePlayers(self): self.players.clear identity = 0 for player in self.playerStaging: playerID = self.playerIdentities[identity] player.assignID(playerID) self.players[playerID] = player identity += 1 def getPlayerNum(self): return self.numPlayers def getComputerName(self): complete = False index = self.numPlayers while not complete: name = self.computerNames[index] complete = True for player in self.playerStaging: if player.getName == name: index += 1 if index >= len(self.computerNames): index = 0 complete = False return self.computerNames[index] def getRandomIdentity(self): For Getting a Random Player for First Turn. return random.choice(self.players.keys) def compileMainMenuElements(self): def getBlankSpace(word, total): return " "*(total-len(word)) def getPlayerBox(playerNum, rowNum): if rowNum == 1: name = self.playerStaging[playerNum-1].getName return '{}{}'.format(name, getBlankSpace(name, 29)) elif rowNum == 2: points = self.playerStaging[playerNum-1].getPoints return 'Points: {}{}'.format(points, getBlankSpace(str(points), 21)) self.mainMenuElements= {'play1row1':'No Player                   ','play1row2':'                             ', 'play2row1':'No Player                   ', 'play2row2':'                            ', 'play3row1':'No Player                   ','play3row2':'                             ', 'play4row1':'No Player                   ', 'play4row2':'                            ', 'play1box':'\033[90m','play2box':'\033[90m','play3box':'\033[90m','play4box':'\033[90m', 'beginBox':'\033[90m','addBox':'\033[97m','removeBox':'\033[90m' }       playerBoxKey = 'play{}box' playerRowKey = 'play{}row{}' i = 1 for j in self.playerStaging: j           colorCode = ['\033[91m','\033[94m','\033[92m','\033[93m'] key = playerBoxKey.format(i) self.mainMenuElements[key] = colorCode[i-1] self.mainMenuElements[playerRowKey.format(i,1)] = getPlayerBox(i, 1) self.mainMenuElements[playerRowKey.format(i,2)] = getPlayerBox(i, 2) i+=1 if self.canBegin: self.mainMenuElements['beginBox'] = '\033[95m' if not self.canAddPlayer: self.mainMenuElements['addBox'] = '\033[90m' if self.canRemovePlayer: self.mainMenuElements['removeBox'] = '\033[97m' def changeComputerSpeed(self): if self.computerSpeed == 'slow': self.computerSpeed = 'normal' elif self.computerSpeed == 'normal': self.computerSpeed = 'fast' elif self.computerSpeed == 'fast': self.computerSpeed = 'slow' def getMainMenuElements(self): return self.mainMenuElements

class Deck: 'shuffle' (bool) : shuffle deck.

colors =    ('red','yellow','green','blue') values =    ('0','1','2','3','4','5','6','7','8','9','X','R','+2') def __init__(self, populate): Initializes proper deck of 108 Uno Cards. self.deck = [] if populate: self.populate(True) def __getitem__(self, index): return self.deck[index] def populate(self, shuffle=True): for color in self.colors: for value in self.values: self.deck.append(Card(color, value)) if value != '0': self.deck.append(Card(color, value)) for i in range(4): i #unused self.deck.append(Card('wild', '+4')) self.deck.append(Card('wild', 'W')) if shuffle: self.shuffle

def __iter__(self): return iter(self.deck)

def __len__(self): return len(self.deck)

def draw(self): return self.deck.pop def place(self, card): return self.deck.append(card) def insert(self, card): self.deck.insert(0, card)

def shuffle(self): random.shuffle(self.deck)

class ComputerPlayer(Player): def __init__(self, name): super.__init__(name) self.type = 'Computer' self.begun = False self.colorsInHand = {'red':0, 'blue':0, 'green':0, 'yellow':0, 'wild':0} self.colorsOutHand = {} self.currentColor = "" def addCard(self, card): Player.addCard(self, card) color = card.getColor self.colorsInHand[color] += 1 def indexCard(self, cardColor, cardValue): for card in self.hand: if card.getValue == cardValue: if cardValue in ('+4', 'W'): return self.hand.indexCard(card) else: if card.getColor == cardColor: return self.hand.indexCard(card) raise ValueError("Card Cannot Be Found") def think(self, match): card = None self.currentColor = match.currentColor currentValue = match.currentValue zeroChangeRule = match.zeroChange twoPlayers = False previousTurnID = match.getNextTurn(True) nextTurnID = match.getNextTurn(False) previousPlayer = match.getPlayer(previousTurnID) #nextPlayer = match.getPlayer(nextTurnID) if previousTurnID == nextTurnID: twoPlayers = True if self.canSkip == False and self.canReverse == True: self.canSkip = True self.canReverse = False self.getLegalCards(self.currentColor, currentValue, zeroChangeRule)

### DRAW CASE ### if len(self.legalCards) == 0 and len(self.wildCards) == 0: return "d" else: ### NO LEGAL CARD, USE WILD CARD ### if len(self.legalCards) == 0: if zeroChangeRule and self.canZeroChange: bestZeroColor = self.getBestColor(self.zeroCards) card = self.getCardByColor(self.zeroCards, bestZeroColor) else: if self.canDrawFour: card = self.getCardByValue(self.wildCards, "+4") print(card) else: card = random.choice(self.wildCards) else: ### HAS LEGAL CARD ### if twoPlayers and self.canSkip: #Always play a skip card in a two player game #print("Shed Skip Strategy") card = self.getCardByValue(self.legalCards,"R", "X") if self.canReverse and previousPlayer.didDraw: #print("Reverse Strategy") reverseCards = self.getAllCardsByValue(self.legalCards, "R") for reverseCard in reverseCards: if reverseCard.getColor == self.currentColor: card = reverseCard if self.canValueChange: # Computer Can Value Change, However, Should it? # Computer Checks to See if Value Change Color is Better Than Current currentColorNum = self.colorsInHand[self.currentColor] bestValueChangeColor = self.getBestColor(self.valueChangeCards) if self.colorsInHand[bestValueChangeColor] > currentColorNum or len(self.valueChangeCards) == len(self.legalCards): card = self.getCardByColor(self.valueChangeCards, bestValueChangeColor) if card == None: #print("Random Strategy") card = random.choice(list(set(self.legalCards) - set(self.valueChangeCards))) color = card.getColor self.colorsInHand[color] -= 1 return str(self.indexCard(card.getColor, card.getValue)) def getWildColor(self): maxKey = max(self.colorsInHand, key=self.colorsInHand.get) if maxKey == 'wild': return random.choice(('r','g','b','y')) else: return maxKey def getCardByValue(self, cardList, *values): for card in cardList: if card.getValue in values: return card def getAllCardsByValue(self, cardList, *values): cards = [] for card in cardList: if card.getValue in values: cards.append(card) return cards def getCardByColor(self, cardList, *colors): for card in cardList: if card.getColor in colors: return card def getBestColor(self, cardList): bestColor = None bestColorNum = 0 for card in cardList: color = card.getColor if self.colorsInHand[color] > bestColorNum: bestColor = color bestColorNum = self.colorsInHand[color] return bestColor

class Card: '''   'suit' (string) : Card's Color (rgby) 'rank' (string) : Card's Value (0-9, R, X, W, +2, +4) '''

colors = { 'red'      :   '\033[91m', 'green'    :   '\033[92m', 'yellow'   :   '\033[93m', 'blue'     :   '\033[94m', 'purple'   :   '\033[95m', 'cyan'     :   '\033[96m', 'white'    :   '\033[97m', 'wild'     :   '', 'dwild'    :   '', 'dred'      :   '\033[31m', 'dgreen'    :   '\033[32m', 'dyellow'   :   '\033[33m', 'dblue'     :   '\033[34m', 'dpurple'   :   '\033[35m', 'dcyan'     :   '\033[36m', 'dwhite'    :   '\033[37m', }   idMap = { 'red':'R','blue':'B','green':'G','yellow':'Y','wild':'W', '0':'0','1':'1','2':'2','3':'3','4':'4','5':'5','6':'6','7':'7','8':'8','9':'9',       '+2':'+','R':'R','W':'W','+4':'$','X':'X'    }

bigNums = { "0" : [" .d888b. ","d88P Y88b","888  888","888   888","888   888","888   888","d88P Y88b"," \"Y888P\" "], "1" : [" d888   "," d8888   ","   888   ","   888   ","   888   ","   888   ","   888   "," 8888888 "], "2" : [".d8888b. ","d88P Y88","d8    888","    .d88P",".od888P\" ","d88P\"    ","888\"     ","888888888"],        "3" : [" .d8888b.","d88P  Y88","     .d88","   8888\" ","     \"Y8b","888    88","Y88b  d88"," \"Y8888P\""],        "4" : ["    d88b ","   d8P88 ","  d8  88 "," d8   88 ","d8    88 ","888888888","      88 ","      88 "],        "5" : ["888888888","888      ","888      ","8888888b ","   \"Y88b ","      888","Y88b d88P","\"Y8888P\" "], "6" : [" .d888b. ","d88P Y88b","888     ","888d888b ","888P \"Y8b","888   888","Y88b d88b"," \"Y888P\" "],        "7" : ["888888888","      d8P","     d8P ","    d8P  "," 8888888 ","  d8P    "," d8P     ","d8P      "],        "8" : [" .d888b. ","d8P  Y8b","Y8b. d8P"," \"Y8888\" "," .dP\"Yb. ","888  888","Y88b d88P"," \"Y888P\" "], "9" : [" .d888b. ","d8P  Y8b","88     88","Y8b.  d88"," \"Y88P888","      888","Y88b d88P"," \"Y888P\" "],        "X" : ["Y8b   d8P"," Y8b d8P ","  Y8o8P  ","   Y8P   ","   d8b   ","  d888b  "," d8P Y8b ","d8P   Y8b"],        "W" : ["88     88","88     88","88  o  88","88 d8b 88","88d888b88","88P   Y88","8P     Y8","P       Y"],        "+2" : ["  db     ","  88     ","C8888D   ","  88 8888","  VP    8","     8888","     8   ","     8888"],        "+4" : ["  db     ","  88     ","C8888D   ","  88   d ","  VP  d8 ","     d 8 ","    d8888","       8 "],        "R9" : ["    d88P ","   d88P  ","  d88P   "," d88P    "," Y88b    ","  Y88b   ","   Y88b  ","    Y88b "],        "R8" : ["   d88P  ","  d88P   "," d88P    ","d88P     ","Y88b     "," Y88b    ","  Y88b   ","   Y88b  "],        "R7" : ["  d88P  Y"," d88P    ","d88P     ","88P      ","88b      ","Y88b     "," Y88b    ","  Y88b  d"],        "R6" : [" d88P  Y8","d88P    Y","88P      ","8P       ","8b       ","88b      ","Y88b    d"," Y88b  d8"], "R5" : ["d88P Y88","88P    Y8","8P      Y","P        ","b        ","8b      d","88b    d8","Y88b  d88"], "R4" : ["88P Y88b","8P    Y88","P      Y8","        Y","        d","b      d8","8b    d88","88b  d88P"], "R3" : ["8P Y88b ","P    Y88b","      Y88","       Y8","       d8","      d88","b    d88P","8b  d88P "], "R2" : ["P Y88b  ","    Y88b ","     Y88b","      Y88","      d88","     d88P","    d88P ","b  d88P  "], "R1" : [" Y88b   ","   Y88b  ","    Y88b ","     Y88b","     d88P","    d88P ","   d88P  ","  d88P   "], "R0" : [" Y88b   ","  Y88b   ","   Y88b  ","    Y88b ","    d88P ","   d88P  ","  d88P   "," d88P    "], }

def __init__(self, color, value): Initializes Uno Card w/ Color and Value. self.wild = False      #Is wild card? self.zero = False self.cardID = '{}{}'.format(self.idMap[color],self.idMap[value]) self.setColor(color) self.setValue(value) self.setPoints(value)

#############################################

### -\/- Retrieve Card Information  -\/- ### def __repr__(self): return "{},{}".format(self.color, self.value)

def getBigNum(self, reverse, reverseSeed=0): Returns list of strings to draw card's value on the pile. bigNums = [] colorCode = self.colorCode colorCodeDark = self.colorCodeDark value = self.value if value == 'R': if not reverse: value += str(reverseSeed) else: value += str(9-reverseSeed) for mid in self.bigNums[value]: bigNums += ['{}| |{}'.format(colorCode,colorCodeDark)+mid+'{}| |\033[0m\t'.format(colorCode)] return bigNums

def getColor(self): Returns card's color. return self.color def getColorCode(self): Returns card's color code. return self.colorCode

def getValue(self): Returns card's value. return self.value def getPoints(self): Returns card's point value. return self.points def getRow(self,rowNum,hide=False): value = self.value displaySpace = self.displaySpace if hide: colorCode = '\033[97m' value = '?' displaySpace = ' ' else: colorCode = self.colorCode if self.isWild: if rowNum == 0: colorCode = '\033[91m' elif rowNum == 1: colorCode = '\033[93m' elif rowNum == 2: colorCode = '\033[92m' elif rowNum == 3: colorCode = '\033[94m' if rowNum == 0: return     '{}\u2666--\u2666\033[0m'.format(colorCode) elif rowNum == 1: return     '{}|{}{}|\033[0m'.format(colorCode, displaySpace, value) elif rowNum == 2: if hide: return  '{}|? |\033[0m'.format(colorCode) else: return  '{}|  |\033[0m'.format(colorCode) elif rowNum == 3: return     '{}\u2666--\u2666\033[0m'.format(colorCode)

#############################################

### -\/- Set Card Information  -\/- ### def setColor(self, color): Sets Card's color and escape code. if color == 'blue': self.color = 'blue' self.colorCode = self.colors['blue'] self.colorCodeDark = self.colors['dblue'] elif color == 'red': self.color = 'red' self.colorCode = self.colors['red'] self.colorCodeDark = self.colors['dred'] elif color == 'yellow': self.color = 'yellow' self.colorCode = self.colors['yellow'] self.colorCodeDark = self.colors['dyellow'] elif color == 'green': self.color = 'green' self.colorCode = self.colors['green'] self.colorCodeDark = self.colors['dgreen'] elif color == 'wild':        #No color modification self.wild = True self.color = 'wild' self.colorCodeDark = self.colors['dwild'] self.colorCode = self.colors['wild']

def setValue(self, value): if value in ('0','1','2','3','4','5','6','7','8','9','X','R','+2','+4','W'): self.value = value self.displaySpace = ' ' if len(value) == 2: self.displaySpace = '' if value == '0': self.zero = True def setPoints(self, value): if value in ('0','1','2','3','4','5','6','7','8','9'): self.points = int(value) elif value in ("W", "+4"): self.points = 50 else: self.points = 20

#############################################

### -\/- Wild Card Methods  -\/- ###

def changeColor(self, color): Changes Card's Color, Intended for Wild Cards. self.setColor(color)

def isWild(self): Returns if card is a wild card. return self.wild def isZero(self): return self.zero class Match:

elementsInit = { ### Names (final) ### 'P1Name':'          ', 'P2Name':'           ', 'P3Name':'           ', 'P4Name':'           ', ### Card Values ### 'P1Cards':'          ', 'P2Cards':'           ', 'P3Cards':'           ', 'P4Cards':'           ', ### Turn Colors / Hand### 'P1Turn':, 'P2Turn':, 'P3Turn':, 'P4Turn':, 'HName':'\t\t', 'HVisual': ,'Hand':, ### Deck ### 'DNum':, 'Deck':[,,,,,,,,], 'PostDNum':'', ### Pile ### 'uHeader':'\t\t\t\t', 'uMiddle':'  ', 'uLower':'   ', 'oHeader':'\t\t\t', 'oMiddle':['\t\t\t','\t\t\t','\t\t\t','\t\t\t','\t\t\t','\t\t\t','\t\t\t','\t\t\t'], ### Messages ### 'Console':, 'Error': }   speeds = {'slow':2,'normal':1,'fast':0}

def __init__(self, gs): ### Decks ### self.deck = Deck(True) self.pile = Deck(False) ### Player Information ### self.players = gs.players self.turnList = [] self.handTitles = {'play1':,'play2':,'play3':,'play4':} ### Carry Information ### self.displayEffects = gs.displayEffects self.hideComputerHands = gs.hideComputerHands self.zeroChange = gs.zeroChange self.computerSpeed = self.speeds[gs.computerSpeed] self.simulation = gs.computerSimulation

### Data ### self.handPosition = 0              # For hand displays self.drawAmount = 0                # Used for force draws self.passes = 0                    # Keep track of consecutive passes for emergency color change self.passMax = 0                   # Max passes before color change self.turn = ''                     # Current turn self.event = ''                    # Wild, Reverse, Skip, etc self.wildColorChange =           # Specifies color to change wild card to        self.currentColor =               # Current color self.currentValue = ''             # Current value self.winnerID = ''                 # ID of Player who Won self.reverse = False               # Is turn order reversed self.turnComplete = False          # Is turn complete self.matchComplete = False         # Is the Game over? self.matchAbort = False            # Did the match conclude without a winner? self.forcedWild = False            # Force change wild

### Initialize Names / Cards / Deck (Assuming New Game) ### self.elements = dict(self.elementsInit) keyStringName = 'P{}Name' keyStringCards = 'P{}Cards' for i in self.players: self.elements[keyStringName.format(i[-1])] = self.players[i].getName+(' '*(11-len(self.players[i].getName))) self.elements[keyStringCards.format(i[-1])] = ' '+(' '*(3-len(str(self.players[i].getCardNum))))+str(self.players[i].getCardNum)+' Cards' self.elements['DNum'] = len(self.deck) if len(str(len(self.deck))) < 2: self.elements['PostDNum'] = '\t' j = 8 for i in range(int(math.ceil(len(self.deck)/12))): self.elements['Deck'][j] = '=' j -= 1 for key in GameSettings.playerIdentities: try: self.buildHandString(key) self.turnList += [key] except KeyError: pass self.passMax = len(self.turnList) def clearShell(self): os.system('cls' if os.name == 'nt' else 'clear')

def begin(self): self.elements['Console'] = 'Beginning Game, Press Enter.' print(self.drawScreen) self.enterBreak self.eventDealCards self.turn = random.choice(self.turnList) self.elements['Console'] = 'First turn will be {}. Press Enter.'.format(self.players[self.turn].getName) print(self.drawScreen(True)) self.enterBreak self.placeCard self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m' if self.event == 'wild': self.eventWildCard elif self.event == 'reverse': self.eventReverse def end(self, gs): if not self.matchAbort: points = 0 self.elements['P{}Turn'.format(self.turn[-1])] = '' self.elements['Console'] = '{} Wins! Press Enter to Begin Point Tally'.format(self.players[self.winnerID].getName) print(self.drawScreen) self.enterBreak for identity in self.turnList: if identity != self.winnerID: self.turn = identity self.elements['HName'] = self.handTitles[self.turn] self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m' while self.players[identity].getCardNum > 0: card = self.players[identity].removeCard(0) points += card.getPoints self.elements['Console'] = '{} Won {} Points!'.format(self.players[self.winnerID].getName,points) keyStringCards = 'P{}Cards' self.elements[keyStringCards.format(identity[-1])] = ' '+(' '*(3-len(str(self.players[identity].getCardNum))))+str(self.players[identity].getCardNum)+' Cards' self.players[identity].maxScroll = math.ceil((self.players[identity].getCardNum / 10)-1) if self.handPosition > self.players[identity].maxScroll: self.handPosition -= 1 self.buildHandVisual(identity) if self.displayEffects and not self.simulation: print(self.drawScreen) time.sleep(.1) self.elements['P{}Turn'.format(self.turn[-1])] = '' self.players[self.winnerID].addPoints(points) self.elements['Console'] = '{} Won {} Points! Press Enter'.format(self.players[self.winnerID].getName,points) print(self.drawScreen) self.enterBreak gs.clearStaging for identity in self.turnList: self.players[identity].discardHand gs.addPlayer(self.players[identity]) return gs   def adjustCardAmount(self, playerID): keyStringCards = 'P{}Cards' self.elements[keyStringCards.format(playerID[-1])] = ' '+(' '*(3-len(str(self.players[playerID].getCardNum))))+str(self.players[playerID].getCardNum)+' Cards' self.players[playerID].maxScroll = math.ceil((self.players[playerID].getCardNum / 10)-1) if self.handPosition > self.players[playerID].maxScroll: self.handPosition -= 1 self.buildHandVisual(playerID)

def buildHandString(self, playerID): playerName = self.players[playerID].getName if len(playerName) < 9: self.handTitles[playerID] = "{}'s Hand\t".format(self.players[playerID].getName) else: self.handTitles[playerID] = "{}'s Hand".format(self.players[playerID].getName)

def buildHandVisual(self, playerID): string = '[' for i in range(self.players[playerID].maxScroll+1): if i == self.handPosition: string += '|' else: string += '-' string += ']' self.elements['HVisual'] = string

def checkInput(self, playerInput): if playerInput == '': return {'valid':False,'entry':playerInput} if playerInput.isnumeric: if int(playerInput)+(10*self.handPosition) < self.players[self.turn].getCardNum: return {'valid':True,'entry':str(int(playerInput)+(10*self.handPosition)),'type':'card'} else: self.elements['Error'] = '{} is not a card.'.format(playerInput) return {'valid':False,'entry':playerInput} else: playerInput = playerInput.lower[0] if playerInput in ['<','>','u','d','p','q','s']: return {'valid':True,'entry':playerInput} else: self.elements['Error'] = '{} is not a valid selection.'.format(playerInput) return {'valid':False,'entry':playerInput}

def checkColorInput(self, playerInput): if playerInput == '': return {'valid':False,'entry':playerInput} playerInput = str(playerInput).lower[0] if playerInput[0] == 'b': return {'valid':True,'entry':'blue'} elif playerInput[0] == 'r': return {'valid':True,'entry':'red'} elif playerInput[0] == 'g': return {'valid':True,'entry':'green'} elif playerInput[0] == 'y': return {'valid':True,'entry':'yellow'} return {'valid':False,'entry':playerInput}

def eventDealCards(self): if self.displayEffects and not self.simulation: self.elements['Console'] = 'Dealing Cards...' for i in ('play1','play2','play3','play4'): if i in self.players: for j in range(7): j #unused self.dealCard(i) if self.displayEffects and not self.simulation: print(self.drawScreen(True)) time.sleep(.1)

def eventReverse(self): if self.displayEffects and not self.simulation: hide = False if self.players[self.turn].getType == "Computer": hide = self.hideComputerHands self.elements['Console'] = "Reverse Card Played! Reversing Turn Order.".format(self.players[self.turn].getName) print(self.drawScreen(hide)) time.sleep(1) for i in range(10): cardBigNums = self.pile[0].getBigNum(self.reverse,i) self.elements['oMiddle'] = cardBigNums print(self.drawScreen(hide)) if self.displayEffects and not self.simulation: time.sleep(.1) cardBigNums = self.pile[0].getBigNum(self.reverse,9) self.elements['oMiddle'] = cardBigNums self.reverse = not self.reverse self.event = '' def eventSkip(self): if self.displayEffects and not self.simulation: hide = False if self.players[self.turn].getType == "Computer": hide = self.hideComputerHands self.elements['Console'] = "Skip Card Placed! Skipping {}'s Turn.".format(self.players[self.turn].getName) print(self.drawScreen(hide)) time.sleep(1) for i in range(2): i #unused self.elements['P{}Turn'.format(self.turn[-1])] = '\033[91m' print(self.drawScreen(hide)) time.sleep(.3) self.elements['P{}Turn'.format(self.turn[-1])] = '' print(self.drawScreen(hide)) time.sleep(.3) self.turnComplete = True self.event = ''

def eventWildCard(self): hide = False if not self.forcedWild: if self.players[self.turn].getType == 'Human': self.elements['Console'] = 'Wild Card! Specifiy a Color: (B)lue, (R)ed, (G)reen, (Y)ellow' self.elements['Error'] = 'Specifiy A Color' print(self.drawScreen) playerInput = str(input("Color Change: ")) checked = self.checkColorInput(playerInput) while not checked['valid']: if checked['entry'] == '<': self.handPosition -= 1 if self.handPosition == -1: self.handPosition = self.players[self.turn].maxScroll self.buildHandVisual(self.turn) elif checked['entry'] == '>': self.handPosition += 1 if self.handPosition > self.players[self.turn].maxScroll: self.handPosition = 0 self.buildHandVisual(self.turn) print(self.drawScreen) playerInput = str(input("Color Change: ")) checked = self.checkColorInput(playerInput) else: hide = self.hideComputerHands checked = self.checkColorInput(self.players[self.turn].getWildColor) self.wildColorChange = checked['entry'] else: self.wildColorChange = self.checkColorInput(random.choice(('r','b','g','y')))['entry'] self.forcedWild = False self.currentColor = self.wildColorChange self.elements['Error'] = "" if self.displayEffects and not self.simulation: self.elements['Console'] = 'Wild Card! Changing Color.' seed = 1 for i in range(10): i #unused if seed > 4: seed = 1 print(self.drawScreen(hide,wildSeed=seed)) time.sleep(.1) seed += 1 self.pile[0].changeColor(self.wildColorChange) self.wildColorChange = '' cardBigNums = self.pile[0].getBigNum(self.reverse) self.elements['oHeader'] = '{}\u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t'.format(self.pile[0].getColorCode) self.elements['oMiddle'] = cardBigNums self.event = '' def eventDraw(self): self.players[self.turn].addForceDraw(self.drawAmount) self.drawAmount = 0 self.event = ''

def dealCard(self, playerID): card = self.deck.draw self.players[playerID].addCard(card) ### Adjust Hand Visual ### self.players[playerID].maxScroll = math.ceil((self.players[playerID].getCardNum / 10)-1) self.handPosition = self.players[playerID].maxScroll self.buildHandVisual(playerID) ### Adjust Player Tile ### keyStringCards = 'P{}Cards' self.elements[keyStringCards.format(playerID[-1])] = ' '+(' '*(3-len(str(self.players[playerID].getCardNum))))+str(self.players[playerID].getCardNum)+' Cards' ### Adjust Deck ### self.elements['DNum'] = len(self.deck) if len(str(len(self.deck))) < 2: self.elements['PostDNum'] = '\t' j = 8 self.elements['Deck'] = [' ',' ',' ',' ',' ',' ',' ',' ', ' '] for i in range(math.ceil(len(self.deck)/12)): i #unused self.elements['Deck'][j] = '=' j -= 1

def placeCard(self, card=None): if card == None: ### Used At Beginning For First Card ### card = self.deck.draw self.elements['DNum'] = len(self.deck) cardColor = card.getColorCode cardBigNums = card.getBigNum(self.reverse) self.currentColor = card.getColor self.currentValue = card.getValue self.pile.insert(card) self.elements['oHeader'] = '{}\u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t'.format(cardColor) self.elements['oMiddle'] = cardBigNums if len(self.pile) > 1: previousCard = self.pile[1] previousCardColor = previousCard.getColorCode self.elements['uHeader'] = '{}     \u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t\t'.format(previousCardColor) self.elements['uMiddle'] = '{}| |\033[0m'.format(previousCardColor) self.elements['uLower'] = '{}\u2666\u2666\u2666\033[0m'.format(previousCardColor) if self.currentColor == 'wild': self.event = 'wild' if self.currentValue == 'X': self.event = 'skip' elif self.currentValue == 'R': if len(self.players) > 2: self.event = 'reverse' else: self.event = 'skip' elif self.currentValue == '+4': self.drawAmount = 4 elif self.currentValue == '+2': self.drawAmount = 2 self.passes = 0 def extractCard(self, playerID, index): card = self.players[playerID].removeCard(index) if self.players[playerID].getCardNum == 0: self.matchComplete = True self.winnerID = self.turn self.adjustCardAmount(playerID) return card def enterBreak(self): if not self.simulation: str(input) return def nextTurn(self): self.turnComplete = False self.handPosition = 0 turnType = self.players[self.turn].getType self.players[self.turn].beginTurn ### Prepare Hand Visuals ### self.elements['HName'] = self.handTitles[self.turn] self.buildHandVisual(self.turn) if self.event == 'skip': self.eventSkip elif self.drawAmount > 0: self.eventDraw while not self.turnComplete: if turnType == 'Human': self.players[self.turn].getLegalCards(self.currentColor, self.currentValue, self.zeroChange) if len(self.deck) > 0: self.elements['Console'] = 'Select a card, (D)raw, or (P)ause.' else: self.players[self.turn].removeForceDraw self.elements['Console'] = 'Select a card, (D)raw, (P)ause, or Pas(s).' if self.players[self.turn].getForceDraws > 0: self.elements['Error'] = 'Draw Card Played! Draw {} cards.'.format(self.players[self.turn].getForceDraws) print(self.drawScreen) playerInput = str(input("\033[97mSelection: \033[92m")) checked = self.checkInput(playerInput) while not checked['valid']: print(self.drawScreen) playerInput = str(input("\033[97mSelection: \033[92m")) checked = self.checkInput(playerInput) playerInput = checked['entry'] if playerInput == '<': self.handPosition -= 1 if self.handPosition == -1: self.handPosition = self.players[self.turn].maxScroll self.buildHandVisual(self.turn) elif playerInput == '>': self.handPosition += 1 if self.handPosition > self.players[self.turn].maxScroll: self.handPosition = 0 self.buildHandVisual(self.turn) elif playerInput == 'd': if len(self.deck) > 0: self.elements['Error'] = '' self.dealCard(self.turn) else: self.elements['Error'] = "Cannot Draw. Deck is Empty" elif playerInput == 'p': pauseOutput = self.pauseScreen if pauseOutput == 'quit': self.matchComplete = True self.turnComplete = True self.winnerID = 'play1' self.matchAbort = True elif playerInput == 's': if len(self.deck) > 0: self.elements['Error'] = "Cannot pass until Deck is empty." elif len(self.players[self.turn].getAllValidCards) > 0: self.elements['Error'] = "Cannot pass while having playable cards." else: self.turnComplete = True self.passes += 1 if self.passes == self.passMax: self.forcedWild = True self.event = 'wild' self.passes = 0 elif playerInput.isnumeric: if self.players[self.turn].getForceDraws == 0: cardCheck = self.players[self.turn].checkCard(playerInput) if cardCheck in self.players[self.turn].getAllValidCards: card = self.extractCard(self.turn, playerInput) self.placeCard(card) self.elements['Error'] = "" self.turnComplete = True else: self.elements['Error'] = "Card Doesn't Match The Color {} or Value {}!".format(self.currentColor, self.currentValue) else: pass elif turnType == 'Computer': self.elements['Console'] = '{}\'s Turn'.format(self.players[self.turn].getName) print(self.drawScreen(self.hideComputerHands)) if not self.simulation: time.sleep(self.computerSpeed) #str(input) while (True): if self.displayEffects and not self.simulation: time.sleep(.2) if self.players[self.turn].getForceDraws > 0 and len(self.deck) > 0: cardIndex = 'd'                   else: cardIndex = self.players[self.turn].think(self) if cardIndex.isnumeric: card = self.extractCard(self.turn, int(cardIndex)) if card.getColor != self.currentColor: self.resetDrawBool self.placeCard(card) self.turnComplete = True break else: if cardIndex == 'd': if len(self.deck) > 0: self.dealCard(self.turn) print(self.drawScreen(self.hideComputerHands)) else: self.turnComplete = True self.players[self.turn].removeForceDraw self.passes += 1 if self.passes == self.passMax: self.forcedWild = True self.event = 'wild' self.passes = 0 break ### DECODE INPUT ### if self.event == 'reverse': self.eventReverse elif self.event == 'wild': self.eventWildCard # Clear Current Turn self.elements['P{}Turn'.format(self.turn[-1])] = '' # Prepare Next Turn self.turn = self.getNextTurn self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m'

def drawScreen(self, hide=False, wildSeed=0): if self.simulation: return '' colorCombos = { 1 : ['\033[91m','\033[93m','\033[92m','\033[94m'], 2 : ['\033[94m','\033[91m','\033[93m','\033[92m'], 3 : ['\033[92m','\033[94m','\033[91m','\033[93m'], 4 : ['\033[93m','\033[92m','\033[94m','\033[91m'] } currentTurn = self.turn if currentTurn == '': currentTurn = self.turnList[-1] hide = True if wildSeed != 0: colorMod = colorCombos[wildSeed] else: colorMod = [,,,]

self.clearShell screenout = '' screenout += '\t\t\033[94m     || ||\033[92m ||\ ||  \033[91m// \\\\\n\033[0m' screenout += '\t\t\033[94m     || ||\033[92m ||\\\|| \033[91m\n\033[0m' screenout += '\t\t\033[94m     \\\ //\033[92m || \|| \033[91m \\\ //\n\033[0m' screenout += '\033[97m===============================================================\n' screenout += '\033[93m{}\033[0m\n'.format(self.elements['Console']) screenout += '\033[97m===============================================================\n' screenout += '\t\t\t\t\t\t'    +        ' \033[97m{}\u2666---\u2666\033[0m\n'.format(self.elements['P1Turn']) screenout += '\033[97mDeck:\t\t'       +       '{}'.format(self.elements['uHeader'])       +       ' \033[97m{}|{}|\033[0m\n'.format(self.elements['P1Turn'],self.elements['P1Name']) screenout += '\033[97m{} Cards'.format(self.elements['DNum'])      +       '{}'.format(self.elements['PostDNum'])+'\t'     +       '{}'.format(self.elements['uHeader'])       +       ' \033[97m{}|{}|\033[0m\n'.format(self.elements['P1Turn'],self.elements['P1Cards']) screenout += '\t\t     '       +      '{}'.format(self.elements['uMiddle'])        +       '\033[97m{}{}'.format(colorMod[0],self.elements['oHeader'])     +      ' \033[97m{}\u2666---\u2666\033[0m\n'.format(self.elements['P1Turn']) screenout += '\033[97m _+_ \t\t      '     +       '{}'.format(self.elements['uMiddle'])                                                                                                   +       '\033[97m{}{}'.format(colorMod[1],self.elements['oHeader'])         +       ' \033[97m{}\u2666---\u2666\033[0m\n'.format(self.elements['P2Turn']) screenout += '\033[97m | '     +       '\033[92m{}\033[0m'.format(self.elements['Deck'][0])        +       '\033[97m |\t\t      '      +       '{}'.format(self.elements['uMiddle'])       +       '\033[97m{}{}'.format(colorMod[2],self.elements['oMiddle'][0])      +       ' \033[97m{}|{}|\033[0m\n'.format(self.elements['P2Turn'],self.elements['P2Name']) screenout += '\033[97m | '     +       '\033[92m{}\033[0m'.format(self.elements['Deck'][1])        +       '\033[97m |\t\t      '      +       '{}'.format(self.elements['uMiddle'])       +       '\033[97m{}{}'.format(colorMod[3],self.elements['oMiddle'][1])      +       ' \033[97m{}|{}|\033[0m\n'.format(self.elements['P2Turn'],self.elements['P2Cards']) screenout += '\033[97m | '     +       '\033[92m{}\033[0m'.format(self.elements['Deck'][2])        +       '\033[97m |\t\t      '      +       '{}'.format(self.elements['uMiddle'])       +       '\033[97m{}{}'.format(colorMod[0],self.elements['oMiddle'][2])      +       ' \033[97m{}\u2666---\u2666\033[0m\n'.format(self.elements['P2Turn']) screenout += '\033[97m | '     +       '\033[93m{}\033[0m'.format(self.elements['Deck'][3])        +       '\033[97m |\t\t      '      +       '{}'.format(self.elements['uMiddle'])       +       '\033[97m{}{}'.format(colorMod[1],self.elements['oMiddle'][3])      +       ' \033[97m{}\u2666---\u2666\033[0m\n'.format(self.elements['P3Turn']) screenout += '\033[97m | '     +       '\033[93m{}\033[0m'.format(self.elements['Deck'][4])        +       '\033[97m |\t\t      '      +       '{}'.format(self.elements['uMiddle'])       +       '\033[97m{}{}'.format(colorMod[2],self.elements['oMiddle'][4])      +       ' \033[97m{}|{}|\033[0m\n'.format(self.elements['P3Turn'],self.elements['P3Name']) screenout += '\033[97m | '     +       '\033[93m{}\033[0m'.format(self.elements['Deck'][5])        +       '\033[97m |\t\t      '      +       '{}'.format(self.elements['uMiddle'])       +       '\033[97m{}{}'.format(colorMod[3],self.elements['oMiddle'][5])      +       ' \033[97m{}|{}|\033[0m\n'.format(self.elements['P3Turn'],self.elements['P3Cards']) screenout += '\033[97m | '     +       '\033[91m{}\033[0m'.format(self.elements['Deck'][6])        +       '\033[97m |\t\t      '      +       '{}'.format(self.elements['uLower'])        +       '\033[97m{}{}'.format(colorMod[0],self.elements['oMiddle'][6])      +       ' \033[97m{}\u2666---\u2666\033[0m\n'.format(self.elements['P3Turn']) screenout += '\033[97m | '     +       '\033[91m{}\033[0m'.format(self.elements['Deck'][7])        +       '\033[97m |\t\t      '      +       '{}'.format(self.elements['uLower'])        +       '\033[97m{}{}'.format(colorMod[1],self.elements['oMiddle'][7])      +       ' \033[97m{}\u2666---\u2666\033[0m\n'.format(self.elements['P4Turn']) screenout += '\033[97m |_'     +     '\033[91m{}\033[0m'.format(self.elements['Deck'][8])          +        '\033[97m_|\t\t         '                                                      +      '\033[97m{}{}'.format(colorMod[2],self.elements['oHeader'])          +       ' \033[97m{}|{}|\033[0m\n'.format(self.elements['P4Turn'],self.elements['P4Name']) screenout += '\033[97m\t\t        '    +                                                                                                                                                                   '\033[97m{}{}'.format(colorMod[3],self.elements['oHeader'])         +       ' \033[97m{}|{}|\033[0m\n'.format(self.elements['P4Turn'],self.elements['P4Cards']) screenout += '\t\t\t\t\t\t'    +       ' \033[97m{}\u2666---\u2666\033[0m\n'.format(self.elements['P4Turn']) screenout += "\033[97m{}".format(self.elements['HName'])       +       "\t\t\t\t {}\n".format(self.elements['HVisual']) screenout += '\033[97m===============================================================\n' screenout += self.players[currentTurn].getHand(self.handPosition,hide) screenout += '\033[91m{}\033[0m'.format(self.elements['Error']) return screenout def pauseScreen(self): while True: self.clearShell print('\n\t\t\tPause') print('\n\t\t1. Resume') print('\t\t2. Quit') selection = str(input('\nSelection: ')).upper while selection not in ['1', '2']: print('\nSelection Invalid') selection = str(input('\nSelection: ')).upper if selection == '1' or "": return "" elif selection == '2': return "quit" def isComplete(self): return self.matchComplete def next(self): self.turn = self.getNextTurn def getNextTurn(self, forceReverse=False): if forceReverse: reverse = not self.reverse else: reverse = self.reverse currentIndex = self.turnList.index(self.turn) if not reverse: if (currentIndex + 1) == len(self.turnList): return self.turnList[0] else: return self.turnList[currentIndex+1] else: if currentIndex == 0: return self.turnList[len(self.turnList) - 1] else: return self.turnList[currentIndex-1] def getPlayer(self, playerID): return self.players[playerID] def resetDrawBool(self): for identity in self.players: self.players[identity].drew = False

def Uno(debugging=False):

###MENUS### def clearShell: os.system('cls' if os.name == 'nt' else 'clear')

def mainMenu: sys.stdout.write("\x1b[8;32;63t") sys.stdout.flush gs = GameSettings while True: print(drawMainMenu(gs)) selection = str(input('\033[97mSelection: \033[92m')) while selection not in ['1', '2', '3', '4', '5']: gs.mainMenuError = "Invalid Selection" print(drawMainMenu(gs)) selection = str(input('\033[97mSelection: \033[92m')) if selection == '1': if gs.canBegin: gs.mainMenuError = "" gs.finalizePlayers gs = playMatch(gs) else: gs.mainMenuError = "Two Players Required to Begin"

elif selection == '2': if gs.canAddPlayer: gs.mainMenuError = "" gs = addPlayer(gs) else: gs.mainMenuError = "Max Number of Players Reached" elif selection == '3': if gs.canAddPlayer: gs.mainMenuError = "" gs = addComputer(gs) else: gs.mainMenuError = "Max Number of Players Reached"

elif selection == '4': if gs.canRemovePlayer: gs.mainMenuError = "" gs = removePlayer(gs) else: gs.mainMenuError = "No Players to Remove"

elif selection == '5': gs.mainMenuError = "" gs = settingsMenu(gs)

else: raise BadInputError('Data Provided Has No Function') def playMatch(gs): for i in range(1): i           m = Match(gs) m.begin while (not m.isComplete): m.nextTurn gs = m.end(gs) return gs   def addPlayer(gs): colors = ['\033[91m','\033[94m', '\033[92m', '\033[93m'] nameOkay = False playerNum = gs.getPlayerNum + 1 colorIndex = playerNum - 1 message = "\033[97mPlease Enter Player {}'s Name: {}".format(playerNum, colors[colorIndex]) while not nameOkay: print(drawMainMenu(gs)) name = str(input(message)).title if len(name) > 11: gs.mainMenuError = "Name Must Be 11 Characters or Less!" elif len(name) == 0: gs.mainMenuError = "" return gs           else: nameOkay = True for player in gs.playerStaging: if player.getName == name: nameOkay = False if nameOkay == False or name in GameSettings.computerNames: gs.mainMenuError = "Name Cannot Match Another Player's Name!" p = Player(name) gs.addPlayer(p) gs.mainMenuError = "" return gs   def addComputer(gs): name = gs.getComputerName c = ComputerPlayer(name) gs.addPlayer(c) return gs   def removePlayer(gs): sys.stdout.write("\x1b[8;{rows};{cols}t".format(rows=32, cols=63)) sys.stdout.flush clearShell complete = False playerNum = gs.getPlayerNum message = "\033[97mPlease Enter Player Number to Remove: \033[91m".format(playerNum) while (not complete): print(drawMainMenu(gs)) number = str(input(message)) if len(number) == 0: gs.mainMenuError = "" return gs           try: number = int(number) if 0 < number <= playerNum: complete = True else: gs.mainMenuError = "Invalid Player Number!" except: gs.mainMenuError = "Please Enter the Player Number, not Name!" gs.mainMenuError = "" gs.removePlayer(number) return gs   def settingsMenu(gs): while True: sys.stdout.write("\x1b[8;32;63t") sys.stdout.flush clearShell print('\n\t\tSettings') print('\n\t1. Draw Effects\t\t\t{}'.format(gs.displayEffects)) print('\t2. Hide Computer Hands\t\t{}'.format(gs.hideComputerHands)) print('\t3. Computer Speed\t\t{}'.format(gs.computerSpeed.title)) #print('\t4. Zero Card Changes Color\t{}'.format(gs.zeroChange)) #print('\t5. Run Simulations\t\t{}'.format(gs.computerSimulation)) print('\n\tA. Exit') selection = str(input('\nSelection: ')).upper while selection not in ('1', '2', '3', '4', '5', 'A', ''): print('\nSelection Invalid') selection = str(input('\nSelection: ')).upper if selection == '1': gs.displayEffects = not gs.displayEffects elif selection == '2': gs.hideComputerHands = not gs.hideComputerHands elif selection == '3': gs.changeComputerSpeed '''           elif selection == '4': gs.zeroChange = not gs.zeroChange elif selection == '5': gs.computerSimulation = not gs.computerSimulation '           elif selection == 'A' or selection ==  or selection in ('4','5'): return gs   def drawMainMenu(gs): clearShell gs.compileMainMenuElements menuElements = gs.getMainMenuElements screenout = '' screenout += '\t\t\033[94m     || ||\033[92m ||\ ||  \033[91m// \\\\\n\033[0m' screenout += '\t\t\033[94m     || ||\033[92m ||\\\|| \033[91m\n\033[0m' screenout += '\t\t\033[94m     \\\ //\033[92m || \|| \033[91m \\\ //\n\033[0m' screenout += '\033[97m===============================================================\033[0m\n' screenout += "{}1-1\033[0m {}2-2\033[0m\n".format(menuElements['play1box'],menuElements['play2box']) screenout += "{}|{}|\033[0m {}|{}|\033[0m\n".format(menuElements['play1box'],menuElements['play1row1'],menuElements['play2box'],menuElements['play2row1']) screenout += "{}|{}|\033[0m {}|{}|\033[0m\n".format(menuElements['play1box'],menuElements['play1row2'],menuElements['play2box'],menuElements['play2row2']) screenout += "{}1-1\033[0m {}2-2\033[0m\n".format(menuElements['play1box'],menuElements['play2box']) screenout += "{}3-3\033[0m {}4-4\033[0m\n".format(menuElements['play3box'],menuElements['play4box']) screenout += "{}|{}|\033[0m {}|{}|\033[0m\n".format(menuElements['play3box'],menuElements['play3row1'],menuElements['play4box'],menuElements['play4row1']) screenout += "{}|{}|\033[0m {}|{}|\033[0m\n".format(menuElements['play3box'],menuElements['play3row2'],menuElements['play4box'],menuElements['play4row2']) screenout += "{}3-3\033[0m {}4-4\033[0m\n".format(menuElements['play3box'],menuElements['play4box']) screenout += "\033[97m===============================================================\033[0m\n" screenout += " {}\u2666---\u2666\033[0m \u2666===========================\u2666\n".format(menuElements['beginBox']) screenout += " {}|1.       Begin Match       |\033[0m |        High Scores        |\n".format(menuElements['beginBox']) screenout += " {}\u2666---\u2666\033[0m \u2666---\u2666\n".format(menuElements['beginBox']) screenout += " {}\u2666---\u2666\033[0m |                           |\n".format(menuElements['addBox']) screenout += " {}|2.       Add Player        |\033[0m |                           |\n".format(menuElements['addBox']) screenout += " {}\u2666---\u2666\033[0m |                           |\n".format(menuElements['addBox']) screenout += " {}\u2666---\u2666\033[0m |                           |\n".format(menuElements['addBox']) screenout += " {}|3.      Add Computer       |\033[0m |                           |\n".format(menuElements['addBox']) screenout += " {}\u2666---\u2666\033[0m |                           |\n".format(menuElements['addBox']) screenout += " {}\u2666---\u2666\033[0m |                           |\n".format(menuElements['removeBox']) screenout += " {}|4.      Remove Player      |\033[0m |                           |\n".format(menuElements['removeBox']) screenout += " {}\u2666---\u2666\033[0m |                           |\n".format(menuElements['removeBox']) screenout += " \033[97m\u2666---\u2666\033[0m |                           |\n" screenout += " \033[97m|5.        Settings         |\033[0m |                           |\n" screenout += " \033[97m\u2666---\u2666\033[0m \u2666===========================\u2666\n" screenout += "\033[97m===============================================================\033[0m\n" screenout += '\033[91m{}\033[0m'.format(gs.mainMenuError) return screenout mainMenu if __name__ == "__main__": Uno