Duel Paws is a 2-player deckbuilding game in which you are the leader of a bunch of cats. You must ensure your opponent’s cats run out of patience before yours do.
This started as a demake of a game called “To Arms!!”, but it has diverged quite a bit and become a very different game. There are still some fundamental similarities.
There is a 2-player pass-and play mode and a single-player mode versus AI. Instructions on how to play are included in the game.
This was made for the Cute Little Demake game jam.
Version 1.2.0 now available! Source and pop can be downloaded on itch.io!
Download right here:
Old content for version 1.0.0
Source code
Duel Paws was written using the pyinsky online python editor. If you want to build this yourself, you can download the project zip:
Duel Paws v1.0.0.zip (27.9 KB)
Also, you can browse the source files here:
main.py
'''
Duel Paws, a 2-player deckbuilding game.
Copyright (C) 2021 wuuff
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
# main.py
import upygame as pygame
from cards import *
screen = pygame.display.set_mode()
pygame.display.set_palette_16bit([
0x0000, 0x194a, 0x790a, 0x0429, 0xa286, 0x5aa9, 0xbe18, 0xff7c, 0xe0c9, 0xf503, 0xf745, 0x5dc9, 0x4d3a, 0x7392, 0xebb4, 0xf654
])
cardSurf = pygame.surface.Surface(16, 16, cardPixels)
cursorSurf = pygame.surface.Surface(16, 16, cursorPixels)
for card in friendlyCards:
card.append(pygame.surface.Surface(8, 8, card[PIXELS]))
for card in hostileCards:
card.append(pygame.surface.Surface(8, 8, card[PIXELS]))
cx = 0
cy = 0
cxmax = 5
ai_enabled = False
def titleScreen():
global cy
global ai_enabled
while True:
random(2) # Call random repeatedly so each game is random
eventtype = pygame.event.poll()
if eventtype != pygame.NOEVENT:
if eventtype.type == pygame.KEYDOWN:
if eventtype.key == pygame.K_DOWN or eventtype.key == pygame.K_UP:
cy = (cy+1)%2
if eventtype.key == pygame.BUT_A:
if cy == 0:
ai_enabled = True
else:
ai_enabled = False
return
if eventtype.key == pygame.BUT_C:
pygame.display.flip()
tutorialScreen()
pygame.draw.text(38,10,"Duel Paws",10)
pygame.draw.text(86,0,"v1.0.0",5)
if cy == 0:
pygame.draw.text(42,30,">VS AI<",10)
pygame.draw.text(46,40,"VS 2P",10)
else:
pygame.draw.text(46,30,"VS AI",10)
pygame.draw.text(42,40,">VS 2P<",10)
pygame.draw.text(18,80,"Press C for tutorial",11)
pygame.display.flip()
def winScreen(which):
while True:
eventtype = pygame.event.poll()
if eventtype != pygame.NOEVENT:
# A hack to make sure title screen isn't skipped: check on button up here
if eventtype.type == pygame.KEYUP:
if eventtype.key == pygame.BUT_A:
titleScreen()
return
pygame.draw.text(32,40,"Player %d Wins!"%(which+1),10)
pygame.display.flip()
def tutorialScreen():
global cx
global cy
textind = 0
initGame()
while True:
eventtype = pygame.event.poll()
if eventtype != pygame.NOEVENT:
if eventtype.type == pygame.KEYDOWN:
if eventtype.key == pygame.BUT_A:
textind += 1
if textind >= len(helpText):
cy = 0
return
if eventtype.key == pygame.BUT_B:
if textind == 0:
cy = 0
return
textind -= 1
renderGame(False)
cy = helpY[textind]
pygame.draw.text(0+1,64,helpText[textind],6)
pygame.display.flip()
enemyHand = []
playerHand = None
playerDiscard = None
playerDeck = None
playerHands = [[],[]]
playerDiscards = [[],[]]
playerDecks = [[],[]]
shopCards = []
patience = 100
patiences = [100,100]
treats = 0
pounces = 0
adopts = 0
rstate = 45
#xorshift random number generator
def random(val):
global rstate
rstate ^= rstate << 7
rstate %= 65536
rstate ^= rstate >> 9
rstate %= 65536
rstate ^= rstate << 8
rstate %= 65536
return rstate % val
currentPlayer = 0
def swapPlayers():
global playerHand
global playerDiscard
global playerDeck
global currentPlayer
global patience
patiences[currentPlayer] = patience
currentPlayer = (currentPlayer+1)%2
playerHand = playerHands[currentPlayer]
playerDiscard = playerDiscards[currentPlayer]
playerDeck = playerDecks[currentPlayer]
patience = patiences[currentPlayer]
def setCXMax(index):
global cxmax
global cx
if index == 0:
cxmax = len(enemyHand)
elif index == 1:
cxmax = len(shopCards)
elif index == 2:
cxmax = len(playerHand)
elif index == 3:
cxmax = len(playerDiscard)
if cxmax == 0:
cxmax = 1
if cx >= cxmax:
cx = cxmax-1
def initCards(hands,discards,decks):
# Clear all cards
global shopCards
global enemyHand
shopCards = []
enemyHand = []
hands[0] = []
hands[1] = []
discards[0] = []
discards[1] = []
decks[0] = []
decks[1] = []
shopCards.append(RANDOMIZE)
enemyHand.append(RANDOMIZE2)
for i in range(5):
enemyHand.append(len(friendlyCards)+random(len(hostileCards)-1))
shopCards.append(random(len(friendlyCards)-1))
# Sleepy cat
discards[0].append(0)
discards[1].append(0)
for i in range(5):
# Scruffy cat
discards[0].append(1)
discards[1].append(1)
def swap(l,a,b):
temp = l[a]
l[a] = l[b]
l[b] = temp
def shuffle(deck):
for i in range(len(deck)):
swap(deck,i, random(len(deck)))
def getCard(index):
if index >= len(friendlyCards):
return hostileCards[index-len(friendlyCards)]
return friendlyCards[index]
def tryDestroy(cards,index):
global treats
global pounces
if len(cards) == 0:
return
card = getCard(cards[index])
if card[COST] <= pounces:
pounces -= card[COST]
if cards[index] == RANDOMIZE2:
# Randomize enemy pool
while len(cards) > 1:
cards.pop()
for i in range(5):
cards.append(len(friendlyCards)+random(len(hostileCards)-1))
elif cards[index] == TASTY_FISH:
# Instantly add treats, don't add card to deck
treats += card[TREATS]
cards.pop(index)
cards.append(len(friendlyCards)+random(len(hostileCards)-1))
else:
cind = cards.pop(index)
cards.append(len(friendlyCards)+random(len(hostileCards)-1))
# Send to other player's discard
playerDiscards[(currentPlayer+1)%2].append(cind)
def tryBuy(cards,index,discard):
global treats
global pounces
if len(cards) == 0:
return
card = getCard(cards[index])
if card[COST] <= treats:
treats -= card[COST]
if cards[index] == RANDOMIZE:
# Randomize shop
while len(cards) > 1:
cards.pop()
for i in range(5):
shopCards.append(random(len(friendlyCards)-1))
elif cards[index] == POWER_NAP:
# Instantly add pounces, don't add card to deck
pounces += card[POUNCES]
cards.pop(index)
cards.append(random(len(friendlyCards)-1))
else:
discard.append(cards[index])
cards.pop(index)
cards.append(random(len(friendlyCards)-1))
def tryAdopt(cards,index):
global adopts
if len(cards) == 0:
return
card = getCard(cards[index])
if adopts > 0:
adopts -= 1
cards.pop(index)
def enemyAction(hand):
global patience
patience -= 2
#for index in hand:
# card = getCard(index)
# patience += card[PATIENCE]
def endTurn():
global cx
global cy
swapPlayers()
enemyAction(enemyHand)
drawCards(playerHand,playerDiscard,playerDeck)
if patience <= 0:
if currentPlayer == 0:
winScreen(1)
else:
winScreen(0)
initGame()
cy = 2
cx = 0
setCXMax(cy)
def tryAction():
if cy == 0:
tryDestroy(enemyHand,cx)
elif cy == 1:
tryBuy(shopCards,cx,playerDiscard)
elif cy == 3:
tryAdopt(playerDiscard,cx)
setCXMax(cy)
def takeInput():
global cx
global cy
eventtype = pygame.event.poll()
if eventtype != pygame.NOEVENT:
if eventtype.type== pygame.KEYDOWN:
if eventtype.key == pygame.K_RIGHT:
cx += 1
cx %= cxmax
if eventtype.key == pygame.K_LEFT:
cx -= 1
if cx < 0:
cx = cxmax-1
if eventtype.key == pygame.K_UP:
cy -= 1
if cy < 0:
cy = 3
setCXMax(cy)
if eventtype.key == pygame.K_DOWN:
cy += 1
cy %= 4
setCXMax(cy)
if eventtype.key == pygame.BUT_B:
endTurn()
if eventtype.key == pygame.BUT_A:
tryAction()
ai_timer = 0
ai_targetx = -1
ai_targety = -1
ai_showhand = True
def setAITarget():
global ai_targetx
global ai_targety
global ai_showhand
if ai_showhand:
ai_targety = 2
ai_targetx = len(playerHand)-1
ai_showhand = False
return
# Adopt hostile cards and sleepy cats
if adopts > 0 and len(playerDiscard) > 0:
for cind in range(len(playerDiscard)):
card = playerDiscard[cind]
if card == 0 or card >= len(friendlyCards):
ai_targety = 3
ai_targetx = cind
return
# Try to buy the most expensive cards it can afford that cost more than 1 (and don't buy power naps)
# Index of zero is randomizer, which we can ignore
most_expensive = 0
most_expensive_ind = 0
for cind in range(len(shopCards)):
cardind = shopCards[cind]
card = getCard(cardind)
if card[COST] > 1 and treats >= card[COST] and cardind != POWER_NAP:
if card[COST] > most_expensive:
most_expensive = card[COST]
most_expensive_ind = cind
if most_expensive > 0:
ai_targety = 1
ai_targetx = most_expensive_ind
return
# Try to buy the most expensive cards it can afford that cost more than 1
# Index of zero is randomizer, which we can ignore
most_expensive = 0
most_expensive_ind = 0
for cind in range(len(enemyHand)):
cardind = enemyHand[cind]
card = getCard(cardind)
if card[COST] > 1 and pounces >= card[COST]:
if card[COST] > most_expensive:
most_expensive = card[COST]
most_expensive_ind = cind
if most_expensive > 0:
ai_targety = 0
ai_targetx = most_expensive_ind
return
# Random chance of randomizing cards
if random(2) == 0:
if random(2) == 0:
if pounces > 0:
ai_targety = 0
ai_targetx = 0
return
elif treats > 0:
ai_targety = 1
ai_targetx = 0
return
else:
if treats > 0:
ai_targety = 1
ai_targetx = 0
return
elif pounces > 0:
ai_targety = 0
ai_targetx = 0
return
def runAIStep():
global cx
global cy
global ai_timer
global ai_targetx
global ai_targety
global ai_showhand
ai_timer += 1
if ai_timer >= 20:
ai_timer = 0
# If no target is set, find a target
if ai_targetx == -1:
setAITarget()
# If after setting it, it's still not set, end turn
if ai_targetx == -1:
endTurn()
ai_targetx = -1
ai_targety = -1
ai_showhand = True
return
if ai_targety < cy:
cy -= 1
setCXMax(cy)
elif ai_targety > cy:
cy += 1
setCXMax(cy)
elif ai_targetx < cx:
cx -= 1
elif ai_targetx > cx:
cx += 1
else:
# On target card
tryAction()
ai_targetx = -1
ai_targety = -1
def drawCards(hand,discard,deck):
global treats
global pounces
global adopts
global patience
treats = 0
pounces = 0
adopts = 0
while len(hand) > 0:
discard.append(hand.pop())
# Hand size may be increased by some cards
handsize = 5
while len(hand) < handsize:
if len(deck) == 0:
if len(discard) == 0:
# If we have completely run out of cards, give up and stop
break
while len(discard) > 0:
deck.append(discard.pop())
shuffle(deck)
index = deck.pop()
card = getCard(index)
handsize += card[EXTRA]
treats += card[TREATS]
pounces += card[POUNCES]
adopts += card[ADOPTS]
patience += card[PATIENCE]
hand.append(index)
# Avoid negative treats and pounces
if treats < 0:
treats = 0
if pounces < 0:
pounces = 0
def renderCards(cards,height):
if len(cards) > 0:
screen.blit(cursorSurf, cx*16+1, height)
for index in range(len(cards)):
cardindex = cards[index]
screen.blit(cardSurf, index*16+1, height)
if cardindex >= len(friendlyCards):
cardindex -= len(friendlyCards)
screen.blit(hostileCards[cardindex][SURFACE], 4+index*16+1, height+4)
else:
screen.blit(friendlyCards[cardindex][SURFACE], 4+index*16+1, height+4)
def renderInfo(cards,height):
# Draw which player's turn it is
if currentPlayer == 0:
pygame.draw.text(100+1,height+16,'P1',11)
else:
if ai_enabled:
pygame.draw.text(100+1,height+16,'AI',12)
else:
pygame.draw.text(100+1,height+16,'P2',12)
# Guard against drawing details when no card is present
if len(cards) == 0:
pygame.draw.text(0+1,height,'No cards here!',6)
return
# Draw card details
index = cards[cx]
if index >= len(friendlyCards):
if index == TASTY_FISH:
pygame.draw.text(64+1,height+8,'When Bought',6)
index -= len(friendlyCards)
pygame.draw.text(0+1,height,hostileCards[index][NAME],6)
pygame.draw.text(77+1,height,'Cost: %dP' % hostileCards[index][COST],6)
if hostileCards[index][TREATS] < 0:
pygame.draw.text(0+1,height+8,'%d Treat' % hostileCards[index][TREATS],6)
elif hostileCards[index][TREATS] > 0:
pygame.draw.text(0+1,height+8,'+%d Treat' % hostileCards[index][TREATS],6)
if hostileCards[index][POUNCES] < 0:
pygame.draw.text(28+1,height+8,'%d Pounce' % hostileCards[index][POUNCES],6)
if hostileCards[index][POUNCES] > 0:
pygame.draw.text(28+1,height+8,'+%d Pounce' % hostileCards[index][POUNCES],6)
if hostileCards[index][PATIENCE] < 0:
pygame.draw.text(64+1,height+8,'%d Patience' % hostileCards[index][PATIENCE],6)
pygame.draw.text(0+1,height+16,hostileCards[index][DESC],6)
else:
pygame.draw.text(0+1,height,friendlyCards[index][NAME],6)
pygame.draw.text(77+1,height,'Cost: %dT' % friendlyCards[index][COST],6)
if friendlyCards[index][TREATS] > 0:
pygame.draw.text(0+1,height+8,'+%d Treat' % friendlyCards[index][TREATS],6)
if friendlyCards[index][POUNCES] > 0:
pygame.draw.text(28+1,height+8,'+%d Pounce' % friendlyCards[index][POUNCES],6)
# Currently, no concurrent adoptions, extra cards, or patience
if friendlyCards[index][PATIENCE] > 0:
pygame.draw.text(64+1,height+8,'+%d Patience' % friendlyCards[index][PATIENCE],6)
if friendlyCards[index][EXTRA] > 0:
pygame.draw.text(64+1,height+8,'+%d Cards' % friendlyCards[index][EXTRA],6)
if friendlyCards[index][ADOPTS] > 0:
pygame.draw.text(64+1,height+8,'+%d Adoption' % friendlyCards[index][ADOPTS],6)
if index == POWER_NAP:
pygame.draw.text(64+1,height+8,'When Bought',6)
pygame.draw.text(0+1,height+16,friendlyCards[index][DESC],6)
def renderGame(showInfo):
drawHeight = 8
pygame.draw.text(0+1,0,"Patience: %d" % patience,8)
pygame.draw.text(60+1,0,"T:%d P:%d A:%d" %(treats,pounces,adopts),10)
pygame.draw.text(0+1,8,"Enemy Forces",7)
if cy == 0:
renderCards(enemyHand,drawHeight+6)
if showInfo:
renderInfo(enemyHand,62)
drawHeight += 22
else:
drawHeight += 8
pygame.draw.text(0+1,drawHeight,"Cat Shoppe",7)
if cy == 1:
renderCards(shopCards,drawHeight+6)
if showInfo:
renderInfo(shopCards,62)
drawHeight += 22
else:
drawHeight += 8
pygame.draw.text(0+1,drawHeight,"Your Hand",7)
if cy == 2:
renderCards(playerHand,drawHeight+6)
if showInfo:
renderInfo(playerHand,62)
drawHeight += 22
else:
drawHeight += 8
pygame.draw.text(0+1,drawHeight,"Your Discard",7)
if cy == 3:
renderCards(playerDiscard,drawHeight+6)
if showInfo:
renderInfo(playerDiscard,62)
drawHeight += 22
else:
drawHeight += 8
pygame.draw.text(0+1,drawHeight,"Info Zone",10)
def initGame():
global patience
global currentPlayer
global cy
global cx
patience = 100
patiences[0] = 100
patiences[1] = 100
currentPlayer = 0
cy = 2
cx = 0
initCards(playerHands,playerDiscards,playerDecks)
swapPlayers()
drawCards(playerHand,playerDiscard,playerDeck)
swapPlayers()
enemyAction(enemyHand)
drawCards(playerHand,playerDiscard,playerDeck)
titleScreen()
initGame()
while True:
if currentPlayer == 0 or (currentPlayer == 1 and not ai_enabled):
takeInput()
else:
runAIStep()
#screen.blit(cardSurf, 14, 14)
#screen.blit(friendlyCards[0][-1], 18, 18)
#print(playerHand)
renderGame(True)
pygame.display.flip()
cards.py
'''
Duel Paws, a 2-player deckbuilding game.
Copyright (C) 2021 wuuff
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
# cards.py
helpText = [
'Duel Paws is a 2-player\ndeckbuilding card game.',
'Each player is in charge\nof a group of cats, but\nthe cats are impatient.',
'Your objective is for your\nopponent to run out of\npatience before you do.',
'Cards play automatically\nand your full hand displays\nat the start of each turn.',
'You have 3 resources:\nTreats, Pounces, and\nAdoptions.',
'Treats can be used to buy\ncats at the shoppe. Bought\ncats go in your discard.',
#'Cards in the "Enemy Forces"\nrow reduce your patience\nat the start of your turn.',
'Pounces are used to defeat\nenemy forces. Enemy cards go\nin your opponent\'s discard.',
'All of the effects on enemy\ncards will happen when they\nare played in your hand.',
'Also, your patience level is\nreduced by 2 at the start\nof your turn.',
'Adoptions remove cards from\nyour discard. Any card in\nyour discard can be adopted.',
'Cards that give an effect\nwhen bought are not added\nto your discard.',
'When your deck runs out of\ncards, your discard is\nshuffled back in your deck.',
'Your deck is not shown.',
'Press A to buy, defeat,\nor adopt cards.\nPress B to end your turn.',
]
helpY = [
2,
2,
2,
2,
2,
1,
0,
0,
0,
3,
3,
3,
3,
3,
]
cardPixels = b'\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\xff\xff\xff\xff\xff\xff\x00\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x00\xff\xff\xff\xff\xff\xff\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\
'
cursorPixels = b'\
\x07\x70\x00\x00\x00\x00\x07\x70\
\x77\xff\xff\xff\xff\xff\xff\x77\
\x7f\x11\x11\x11\x11\x11\x11\xf7\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x0f\x11\x11\x11\x11\x11\x11\xf0\
\x7f\x11\x11\x11\x11\x11\x11\xf7\
\x77\xff\xff\xff\xff\xff\xff\x77\
\x07\x70\x00\x00\x00\x00\x07\x70\
'
sleepyCatPixels = b'\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x16\x11\x11\x11\
\x61\x61\x61\x61\
\x11\x61\x66\x66\
\x16\x66\x65\x65\
\x16\x66\x66\x66\
\x66\x66\x66\x66\
'
scruffyCatPixels = b'\
\x11\x11\x11\x11\
\x14\x14\x11\x11\
\x45\x45\x41\x11\
\x44\x44\x41\x14\
\x14\x84\x11\x44\
\x14\x44\x44\x41\
\x14\x44\x44\x41\
\x44\x41\x14\x41\
'
cuteCatPixels = b'\
\x11\x11\x11\x11\
\x11\xee\x1e\xe1\
\x11\xee\xee\xe1\
\x11\x5e\x6e\x51\
\x11\x51\x61\x51\
\x11\x66\x66\x61\
\x11\x56\x65\x11\
\x15\x56\x66\x11\
'
partyCatPixels = b'\
\x11\x11\x11\x81\
\x11\x11\x1e\x81\
\x16\x11\x18\x88\
\x61\x61\x8e\x8e\
\x11\x61\x66\x66\
\x16\x66\x65\x65\
\x16\x66\x66\x66\
\x66\x66\x66\x66\
'
chillCatPixels = b'\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x21\x21\x11\x11\
\x22\x21\x11\x11\
\x22\x2d\xdd\xd1\
\xdd\xdd\xdd\xd2\
\x22\x2d\x22\x22\
\x11\x11\x11\x11\
'
socialCatPixels = b'\
\x11\x11\x11\x16\
\x11\x11\x11\x16\
\x91\x11\x11\x81\
\x19\x19\x11\x18\
\x91\x19\x91\x18\
\x99\x99\x91\x81\
\x99\x91\x11\x11\
\x91\x91\x11\x11\
'
coffeeCatPixels = b'\
\x11\x44\x41\x11\
\x11\x11\x14\x14\
\x11\x41\x44\x41\
\x16\x44\x44\x11\
\x14\x44\x11\x11\
\x11\x41\x11\x11\
\x14\x11\x11\x11\
\x11\x11\x11\x11\
'
wharfCatPixels = b'\
\x16\x16\x11\x11\
\x16\x66\x11\x11\
\x16\x66\x16\x11\
\x16\x6d\x11\x61\
\x16\x66\x14\x41\
\x1d\x66\x64\x41\
\x44\x44\x44\x44\
\x11\x11\x14\x41\
'
hunterCatPixels = b'\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x11\x19\x19\x11\
\x11\x17\x97\x13\
\x13\x13\x99\x31\
\x31\x39\x39\x31\
\x11\x3b\x39\x31\
\x11\x13\x33\xb1\
'
demandingCatPixels = b'\
\x11\x11\x11\x11\
\x51\x11\x11\x15\
\x55\x11\x11\x55\
\x55\x51\x16\x55\
\x55\x55\x66\x55\
\x57\x06\x67\x05\
\x50\x06\x60\x05\
\x56\x6e\x55\x55\
'
patientCatPixels = b'\
\x11\x11\x11\x11\
\x11\x11\xff\x11\
\x11\x1f\x11\xf1\
\x11\x11\x11\x1f\
\x11\x11\x1f\xff\
\x1f\x11\xff\xff\
\x7f\x1f\xf1\x1f\
\xff\xff\x11\xf1\
'
zenCatPixels = b'\
\x11\xf1\xf1\x11\
\x11\x7f\x71\x11\
\xf1\xff\xf1\xf1\
\x1f\xff\xff\x11\
\x11\xff\xf1\x11\
\x1f\xff\xff\x61\
\x11\xf1\xf1\x16\
\x11\x11\x11\x61\
'
supermodelCatPixels = b'\
\x11\x17\x11\x11\
\x11\xc7\x11\x11\
\x11\x77\x11\x11\
\x11\x17\x71\x11\
\x11\x17\x71\x71\
\x11\x17\x71\x17\
\x11\x77\x77\x17\
\x11\x77\x71\x71\
'
unknownPixels = b'\
\x11\x11\x11\x11\
\x11\x1a\xa1\x11\
\x11\xa1\x1a\x11\
\x11\x11\x1a\x11\
\x11\x11\xa1\x11\
\x11\x1a\x11\x11\
\x11\x11\x11\x11\
\x11\x1a\x11\x11\
'
shufflePixels = b'\
\x11\x11\x11\x11\
\x11\x1a\xa1\x11\
\x11\xa1\x11\x11\
\xa1\xa1\x11\xa1\
\x1a\x11\x1a\x1a\
\x11\x11\x1a\x11\
\x11\x1a\xa1\x11\
\x11\x11\x11\x11\
'
powerNapPixels = b'\
\xcc\xc1\x11\x11\
\x11\xc1\x11\x11\
\x1c\x11\x11\x11\
\xc1\x11\x1c\xcc\
\xcc\xc1\x11\x1c\
\x11\x11\x11\xc1\
\x11\x11\x1c\x11\
\x11\x11\x1c\xcc\
'
shadowPixels = b'\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x11\xdd\xdd\x11\
\x1d\xdd\xdd\xd1\
\x11\xdd\xdd\x11\
\x11\x11\x11\x11\
'
leafPixels = b'\
\x11\x11\x33\x11\
\x11\x33\x3b\xb1\
\x13\x3b\xb3\x31\
\x13\xb3\x33\x31\
\x13\xb3\x33\x11\
\x1b\x33\x31\x11\
\x1b\x11\x11\x11\
\x11\xb1\x11\x11\
'
bugPixels = b'\
\x11\x1b\x31\x11\
\xd1\x32\x22\x1d\
\x1d\x12\x21\xd1\
\x11\xb3\x32\x11\
\xdd\x32\x22\xdd\
\x11\x22\x22\x11\
\x1d\x12\x21\xd1\
\xd1\x11\x11\x1d\
'
scruffyDogPixels = b'\
\x11\x11\x11\x11\
\x14\x44\x44\x41\
\x44\x44\x44\x44\
\x44\x44\x44\x44\
\x44\x44\x54\x54\
\x45\x44\x54\x54\
\x45\x55\x55\x54\
\x45\x5d\xd5\x54\
'
fastDogPixels = b'\
\x11\x11\x11\x11\
\x11\x61\x11\x16\
\x67\x61\x66\x16\
\x66\x66\x66\x61\
\x11\x66\x16\x61\
\x16\x11\x11\x66\
\x61\x11\x11\x16\
\x11\x11\x11\x11\
'
scaryDogPixels = b'\
\x11\x51\x15\x11\
\x15\x51\x15\x51\
\x15\x85\x58\x51\
\x15\x55\x55\x51\
\x15\x52\x25\x51\
\x11\x56\x56\x11\
\x11\x55\x55\x11\
\x15\x55\x55\x51\
'
slobberyDogPixels = b'\
\x11\x13\x74\x37\
\x1d\x44\x44\x77\
\x1d\x44\x44\x44\
\x11\x44\x44\x54\
\x11\x88\x55\x44\
\x18\x88\x44\x44\
\x18\x88\x11\x14\
\x11\x81\x11\x11\
'
laserPointerPixels = b'\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x11\x88\x11\x11\
\x11\x88\x11\x11\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
\x11\x11\x11\x11\
'
fishmongerPixels = b'\
\x11\x55\x11\x11\
\x11\xff\x11\x11\
\x11\xff\x11\x11\
\xc4\xcc\x4c\xcc\
\xc4\xcc\x41\x16\
\xc4\x44\x41\x16\
\x14\x44\x41\x11\
\x15\x11\x51\x11\
'
tastyFishPixels = b'\
\x11\x11\x11\x11\
\x11\x11\x16\x61\
\x11\x66\x65\x61\
\x11\x16\x66\x61\
\x11\x66\x66\x11\
\x66\x66\x61\x11\
\x11\x61\x11\x11\
\x11\x61\x11\x11\
'
NAME = 0
COST = 1
TREATS = 2
POUNCES = 3
PATIENCE = 4
EXTRA = 5
ADOPTS = 6
DESC = 7
PIXELS = 8
SURFACE = 9
# Name, Cost, Treats, Pounces, Patience, Extra Cards, Adopt, Description, Pixels
friendlyCards = [\
['Sleepy Cat',1,0,1,0,0,0,'Recharging...',sleepyCatPixels],\
['Scruffy Cat',1,1,0,0,0,0,'Looks hungry',scruffyCatPixels],\
['Cute Cat',2,0,0,0,0,1,'Illegally adorable',cuteCatPixels],\
['Party Cat',4,0,1,0,1,0,'Here to party',partyCatPixels],\
['Chill Cat',4,1,0,0,1,0,'Here to chill',chillCatPixels],\
['Social Cat',4,0,0,0,2,0,'Brings friends',socialCatPixels],\
['Coffee Cat',3,0,2,0,0,0,'Woah now cat',coffeeCatPixels],\
['Wharf Cat',3,2,0,0,0,0,'Big tuna',wharfCatPixels],\
['Hunter Cat',5,0,3,0,0,0,'Master pouncer',hunterCatPixels],\
['Demanding Cat',5,3,0,0,0,0,'He wants snacks',demandingCatPixels],\
['Patient Cat',4,0,0,1,0,0,'Waiting to strike',patientCatPixels],\
['Zen Cat',5,0,0,2,0,0,'Unperturbed',zenCatPixels],\
['Supermodel Cat',4,0,0,0,0,2,'Star of the catwalk',supermodelCatPixels],\
['Power Nap',2,0,1,0,0,0,'Pounce fuel',powerNapPixels],\
['Randomize Shoppe',1,0,0,0,0,0,'Mix things up',shufflePixels],\
]
RANDOMIZE = len(friendlyCards)-1
POWER_NAP = RANDOMIZE-1
# Name, Cost, Treats, Pounces, Patience, Extra Cards, Adopt, Description
hostileCards = [\
['Shadow',3,0,0,0,0,0,'High definition',shadowPixels],\
['Leaf',4,0,0,-1,0,0,'Suspicious',leafPixels],\
['Bug',5,0,0,-2,0,0,'It moves funny',bugPixels],\
['Scruffy Dog',4,-1,0,0,0,0,'Will eat everything',scruffyDogPixels],\
['Fast Dog',4,0,-1,0,0,0,'Loves chasing',fastDogPixels],\
['Scary Dog',5,0,-1,-1,0,0,'Spooky',scaryDogPixels],\
['Slobbery Dog',5,-1,0,-1,0,0,'Slobbers on the treats!',slobberyDogPixels],\
['Laser Pointer',3,0,3,-2,0,0,'It always escapes',laserPointerPixels],\
['Fishmonger',3,3,0,-2,0,0,'Unfortunately likes dogs',fishmongerPixels],\
['Tasty Fish',2,1,0,0,0,0,'Worth pouncing',tastyFishPixels],\
['Randomize Enemies',1,0,0,0,0,0,'Try a new part of town',shufflePixels],\
]
RANDOMIZE2 = RANDOMIZE+len(hostileCards)
TASTY_FISH = RANDOMIZE2-1