mostly working

This commit is contained in:
Francesco Mecca 2019-08-21 18:28:41 +02:00
parent ba3758e93f
commit 71c277853d
10 changed files with 223 additions and 67 deletions

View file

@ -20,4 +20,4 @@
LOADING... WAIT...

View file

@ -20,4 +20,4 @@
Φ╚╫╫╫╫` ▀╬╫N╨▌ Φ╚╫╫╫╫` ▀╬╫N╨▌
▒╩╫╫╫▌ ▀╫╫╧* ▒╩╫╫╫▌ ▀╫╫╧*
LOADING... WAIT...

View file

@ -20,4 +20,4 @@
"╩Ñ╬▌ ╙ÑÑ╨` "╩Ñ╬▌ ╙ÑÑ╨`
LOADING... WAIT...

View file

@ -20,4 +20,4 @@
` .╬]╫╫╫╫╛ ╙▓╫╫N╨╫⌐ ` ` .╬]╫╫╫╫╛ ╙▓╫╫N╨╫⌐ `
"╩Ñ╣▀ ╙ÑÑ" "╩Ñ╣▀ ╙ÑÑ"
LOADING... WAIT...

View file

@ -20,4 +20,4 @@
'╝╨'"╜▀ßM^` ▒╨╫╫╫╫⌐ ▀╬╫Ñ╙╫⌐ └╝╧╙└` ╜┘ '╝╨'"╜▀ßM^` ▒╨╫╫╫╫⌐ ▀╬╫Ñ╙╫⌐ └╝╧╙└` ╜┘
"╩ÑÑ╩ ▀ÑÑ"` "╩ÑÑ╩ ▀ÑÑ"`
LOADING... WAIT...

View file

@ -11,12 +11,12 @@ from state import Table, Hand
from metro_holografix.cardtypes import * from metro_holografix.cardtypes import *
import state import state
logging.basicConfig(level=logging.INFO, filename='game.log', filemode='a', format='%(levelname)s - %(message)s') logging.basicConfig(level=logging.DEBUG, filename='/tmp/game.log', filemode='a', format='%(levelname)s - %(message)s')
logging.info("START") logging.info("START")
action = '' action = ''
exit = False exit = False
ID = "you" ID = "YOU"
class FrameFactory: class FrameFactory:
titles = ['0x10', '0x11', '0x12', '0x13', '0x14', '0x15', '0x16', '0x17', titles = ['0x10', '0x11', '0x12', '0x13', '0x14', '0x15', '0x16', '0x17',
@ -101,7 +101,16 @@ class FrameFactory:
self.hand = w self.hand = w
def getChoices(self): def getChoices(self):
src = (None, None); dst = None def make_card(w):
s = w.items[w.choice][1]
if s == ' ':
s = w.items[1][1]; assert w.choice == 2
v = w.items[w.choice][-3]
ve = 13 if v == 'K' else 12 if v == 'Q' else 11 if v == 'J' else 10 if v == '0' else int(v)
se = 'Pikes' if s == '' else 'Hearts' if s == '' else 'Tiles' if s == '' else 'Clovers'
return Card(se, ve)
src = (None, None); dst = None; card = None
if self.widgets[0].choice == 0: if self.widgets[0].choice == 0:
dst = 'Empty' dst = 'Empty'
@ -111,11 +120,15 @@ class FrameFactory:
for i, w in enumerate(self.widgets[1:]): for i, w in enumerate(self.widgets[1:]):
if w.choice == 0: if w.choice == 0:
assert dst != 'Empty' assert dst != 'Empty'
logging.debug(f'{w.items} , {i}: {w.choice}')
dst = i dst = i
elif w.choice > 1: elif w.choice > 1:
assert src[0] != 'Hand' assert src[0] != 'Hand'
logging.debug(f'{w.items} , {i}: {w.choice}')
src = i, w.choice-2 src = i, w.choice-2
return src, dst card = make_card(w)
return src, dst, card
def makeButtons(dialog, stats): def makeButtons(dialog, stats):
buttonSend = WColoredButton(7, "SND", C_RED) buttonSend = WColoredButton(7, "SND", C_RED)
@ -196,7 +209,7 @@ def spawn_and_wait(tstr, difficulty):
output = r.read() output = r.read()
return output return output
def validate_auto_play(original, nl): def validate_auto_play(otable, ohand, nl):
# nl is a nested list of taggedcards, but without type # nl is a nested list of taggedcards, but without type
# must reconstruct # must reconstruct
def make_cards(l): def make_cards(l):
@ -207,17 +220,39 @@ def validate_auto_play(original, nl):
hand = Hand([c for cards in [p.cards for p in pp if p.tag == 'NonValido'] for c in cards]) hand = Hand([c for cards in [p.cards for p in pp if p.tag == 'NonValido'] for c in cards])
table = Table([p for p in pp if p.tag == 'Valido']) table = Table([p for p in pp if p.tag == 'Valido'])
assert len(table.cards) == 0 or table.is_valid() assert len(table.cards) == 0 or table.is_valid()
if original.equality(table) == True: assert len(otable.flatten()) + len(ohand.cards) == len(hand.cards) + len(table.flatten())
if otable.equality(table) == True:
return 'DRAW' return 'DRAW'
else: else:
return table, hand return table, hand
def dispatchMove(game, src, dst, to_move):
if src[0] is None or src[1] is None or dst is None:
return
else:
table, hand = game.last()
t, h = None, None
if src[0] == 'Hand' and dst == 'Empty':
t, h = state.fromHandToEmpty(table, hand, src[1])
elif src[0] == 'Hand' and type(dst) is int:
t, h = state.fromHandToTable(table, hand, src[1], dst)
elif type(src[0]) is int and dst == 'Empty':
t, h = state.fromTableToEmpty(table, hand, src, to_move)
elif type(src[0]) is int and type(dst) is int:
t, h = state.fromTableToTable(table, hand, src, dst, to_move)
else:
assert False
assert t is not None and h is not None
logging.info(f"MOVE ({game.nrounds}): {game.cur_player} = {src}:{dst}")
return game.advance(t, h)
def make_auto_move(original, game, difficulty): def make_auto_move(original, game, difficulty):
table, hand = game.last() table, hand = game.last()
tstr = state.toJson(table, hand) tstr = state.toJson(table, hand)
output = spawn_and_wait(tstr, difficulty) output = spawn_and_wait(tstr, difficulty)
res = validate_auto_play(original, json.loads(output)) res = validate_auto_play(table, hand, json.loads(output))
if type(res) is str: if type(res) is str:
logging.info(f"BOT-DRAW ({game.nrounds}): {game.cur_player} = {game.last()}") logging.info(f"BOT-DRAW ({game.nrounds}): {game.cur_player} = {game.last()}")
game.draw() game.draw()
@ -230,10 +265,12 @@ def make_auto_move(original, game, difficulty):
game.next_turn() game.next_turn()
def main(difficulty): def main(difficulty, dbg=False):
global exit, action global exit, action
game = state.State(["bot1", ID]) dbgCnt = 0
game = state.State(ID, ["PVR", ID])
# game = state.State([ID, "bot1"]) # game = state.State([ID, "bot1"])
game.next_turn() game.next_turn()
@ -243,8 +280,11 @@ def main(difficulty):
make_auto_move(game.last()[0], game, difficulty) make_auto_move(game.last()[0], game, difficulty)
if game.hasEnded == True: if game.hasEnded == True:
break break
if game.hasEnded == True:
break if dbgCnt >= 3:
dbgCnt = 0
from IPython import embed as fuck
fuck()
with Context(): with Context():
@ -256,9 +296,12 @@ def main(difficulty):
f = FrameFactory(dialog) f = FrameFactory(dialog)
stats = f' Round: {game.nrounds} - ' stats = f' Round: {game.nrounds} - '
for idp, h in game.players.items(): if game.hasEnded:
stats += f'{idp}: {len(h.cards)}, ' stats += f'Winner: {game.winner}'
stats = stats[:-2] + ' ' # remove last comma else:
for idp, h in game.players.items():
stats += f'{idp}: {len(h.cards)}, '
stats = stats[:-2] + ' ' # remove last comma
makeButtons(dialog, stats) makeButtons(dialog, stats)
#### FRAMES #### #### FRAMES ####
@ -271,17 +314,16 @@ def main(difficulty):
res = dialog.loop() res = dialog.loop()
if res == 1001 or res == 9: # or res == KEY_END or res == KEY_ESC: # 1001 is exit? # 9 is ctrl-c if res == 1001 or res == 9: # or res == KEY_END or res == KEY_ESC: # 1001 is exit? # 9 is ctrl-c
exit = True exit = True
elif game.hasEnded:
pass
else: else:
if action == 'EXIT': if action == 'EXIT':
exit = True exit = True
elif action == 'MOVE' or res == KEY_ENTER or res == b'm': elif action == 'MOVE' or res == KEY_ENTER or res == b'm':
# TODO: transition effect # TODO: transition effect
src, dst = f.getChoices() src, dst, ccard = f.getChoices()
if src[0] is not None and src[1] is not None and dst is not None: logging.debug(ccard)
game.move_and_advance(src, dst) # get them from next dispatchMove(game, src, dst, ccard)
logging.info(f"MOVE ({game.nrounds}): {game.cur_player} = {src}:{dst}")
else:
continue
elif action == 'DRAW' or res == b'd': elif action == 'DRAW' or res == b'd':
logging.info(f"DRAW ({game.nrounds}): {game.cur_player} = {game.last()}") logging.info(f"DRAW ({game.nrounds}): {game.cur_player} = {game.last()}")
game.draw() game.draw()
@ -303,27 +345,40 @@ def main(difficulty):
elif action == 'BACK': elif action == 'BACK':
game.backtrack() game.backtrack()
logging.info(f"BACK ({game.nrounds}): {game.cur_player}") logging.info(f"BACK ({game.nrounds}): {game.cur_player}")
elif res == b'p' and dbg == True:
dbgCnt += 1
else: else:
pass pass
if game.hasEnded: if game.hasEnded:
print(f'{Fore.RED}' + "Game has ended, player '" + game.winner + "' has won"+f'{Style.RESET_ALL}') print(f'{Fore.RED}' + "Game has ended, player '" + game.winner + "' has won"+f'{Style.RESET_ALL}')
else:
s = input(f'{Fore.MAGENTA}Do you want to save the game? (y/n)\n')
while s.lower() not in ['y', 'yes', 'n', 'no']:
s = input(f"{Fore.MAGENTA}Please write 'y' or 'n'\n")
print(f'{Style.RESET_ALL}')
if s.lower() == 'y' or s.lower() == 'yes':
game.dump()
if __name__ == '__main__': if __name__ == '__main__':
from sys import argv from sys import argv
print(argv[1]) print(argv[1])
diff = argv[1] diff = argv[1]
dbg = 'DEBUG' in argv
if diff == 'easy': if diff == 'easy':
main(7) main(7, dbg)
elif diff == 'medium': elif diff == 'medium':
main(14) main(14, dbg)
elif diff == 'hard': elif diff == 'hard':
main(21) main(21, dbg)
else: else:
try: try:
diff = int(diff) diff = int(diff)
except: except:
print('Wrong argument for difficulty') print('Wrong argument for difficulty')
main(int(diff)) main(int(diff), dbg)
print('cli interface')
print('initial screen')

1
ono_sendai/save.final Normal file
View file

@ -0,0 +1 @@
{"table": [[["Clovers", 3], ["Hearts", 3], ["Pikes", 3], ["Tiles", 3]], [["Clovers", 8], ["Hearts", 8], ["Pikes", 8]], [["Clovers", 13], ["Hearts", 13], ["Tiles", 13]], [["Clovers", 2], ["Hearts", 2], ["Tiles", 2]], [["Clovers", 1], ["Hearts", 1], ["Tiles", 1]], [["Clovers", 4], ["Pikes", 4], ["Tiles", 4]], [["Hearts", 5], ["Hearts", 6], ["Hearts", 7], ["Hearts", 8]], [["Clovers", 10], ["Clovers", 11], ["Clovers", 9]], [["Hearts", 2], ["Hearts", 3], ["Hearts", 4]], [["Pikes", 1], ["Pikes", 12], ["Pikes", 13]], [["Hearts", 10], ["Hearts", 11], ["Hearts", 12]]], "PVR": [["Clovers", 2], ["Pikes", 5], ["Clovers", 6], ["Hearts", 7], ["Pikes", 7], ["Pikes", 7], ["Pikes", 9], ["Tiles", 9], ["Tiles", 11], ["Tiles", 11]], "YOU": [["Tiles", 6], ["Clovers", 7], ["Tiles", 9], ["Hearts", 10], ["Pikes", 10], ["Pikes", 11], ["Tiles", 12], ["Tiles", 13]], "nrounds": 25, "players": ["PVR", "YOU"]}

View file

@ -88,7 +88,9 @@ class WrongMoveException(Exception):
pass pass
class State: class State:
def __init__(self, ids): def __init__(self, human, ids):
assert human in ids
self.humanPlayer = human
self.deck = make_deck() self.deck = make_deck()
self.winner = None self.winner = None
self.hasEnded = False self.hasEnded = False
@ -124,8 +126,8 @@ class State:
if original.equality(table): if original.equality(table):
raise WrongMoveException() raise WrongMoveException()
elif not table.is_valid() or len(set(original.flatten()) - set(table.flatten())) != 0: elif not table.is_valid() or len(set(original.flatten()) - set(table.flatten())) != 0:
if self.cur_player != 'you': if self.cur_player != self.humanPlayer:
fuck() # debug fuck() # debug # TODO: should remove
raise WrongMoveException() raise WrongMoveException()
else: else:
self.table, self.players[self.cur_player] = table, hand self.table, self.players[self.cur_player] = table, hand
@ -147,16 +149,34 @@ class State:
def size(self): def size(self):
return len(self.turn) return len(self.turn)
def move_and_advance(self, src, dst):
table, hand = self.last()
t, h = gioca(table, hand, src, dst)
self.turn.append((t, h))
return t, h
def advance(self, table, hand): def advance(self, table, hand):
self.turn.append((table, hand)) self.turn.append((table, hand))
return table, hand return table, hand
def dump(self):
j = dict()
j['table'] = [tc.cards for tc in self.table.cards]
for pl, hand in self.players.items():
j[pl] = hand.cards
j['nrounds'] = self.nrounds
j['players'] = list(self.players.keys())
with open('save.machiavelli', 'w') as f:
f.write(json.dumps(j))
return j
def load(self):
with open('save.machiavelli', 'r') as f:
j = json.loads(f.read())
self.nrounds = j['nrounds']
tcards = []
for tc in j['table']:
tcards.append(TaggedCards([Card(seed, value) for seed, value in tc]))
self.table = Table(tcards)
self.players = dict()
for pl in j['players']:
self.players[pl] = Hand([Card(seed, value) for seed, value in j[pl]])
def fromJson(j): def fromJson(j):
hcards = [Card(seed, value) for seed, value in j['hand']] hcards = [Card(seed, value) for seed, value in j['hand']]
tcards = [] tcards = []
@ -172,30 +192,110 @@ def toJson(table, hand):
j['table'].append(tc.cards) j['table'].append(tc.cards)
return json.dumps(j) return json.dumps(j)
# TODO: refactor language # def gioca(tavolo, hand, src, dst):
def gioca(tavolo, hand, src, dst): # giocata = [] if dst == 'Empty' else tavolo.cards[dst]
giocata = [] if dst == 'Empty' else tavolo.cards[dst] # da_muovere = hand.cards[src[1]] if src[0] == 'Hand' else tavolo.cards[src[0]].cards[src[1]]
da_muovere = hand.cards[src[1]] if src[0] == 'Hand' else tavolo.cards[src[0]].cards[src[1]] # hcards = hand.cards[:src[1]] + hand.cards[src[1]+1:] if src[0] == 'Hand' else hand.cards
hcards = hand.cards[:src[1]] + hand.cards[src[1]+1:] if src[0] == 'Hand' else hand.cards # assert src[0] != 'Hand' or len(hcards) == len(hand.cards) - 1
assert src[0] != 'Hand' or len(hcards) == len(hand.cards) - 1
assert type(dst) is int or dst == 'Empty' # assert type(dst) is int or dst == 'Empty'
assert type(src[0]) is int or src[0] == 'Hand' # assert type(src[0]) is int or src[0] == 'Hand'
assert type(da_muovere) is Card # assert type(da_muovere) is Card
assert type(giocata) is TaggedCards or giocata == [] # assert type(giocata) is TaggedCards or giocata == []
idx = -1 if dst == 'Empty' else tavolo.cards.index(giocata) # idx = -1 if dst == 'Empty' else tavolo.cards.index(giocata)
news = [TaggedCards([da_muovere])] if type(giocata) is list else [] # if type(giocata) is list: # we want a new empty cell
rimpiazzata = False # news = [TaggedCards([da_muovere])]
for i, t in enumerate(tavolo.cards): # else:
if i == idx: # news = []
p = TaggedCards(giocata.cards + [da_muovere])
news.append(p) def fromHandToEmpty(table, hand, src):
elif not rimpiazzata and da_muovere in t.cards: assert type(src) is int
t = [c for c in t.cards if c != da_muovere] to_move = hand.cards[src]
if t != []: hcards = hand.cards[:src] + hand.cards[src+1:]
news.append(TaggedCards(t)) assert len(hcards) == len(hand.cards) - 1
rimpiazzata = True
assert type(to_move) is Card
news = [TaggedCards([to_move])] + table.cards
newTable = Table(news)
assert len(newTable.flatten()) + len(hcards) == len(hand.cards) + len(table.flatten()), fuck()
return newTable, Hand(hcards)
def fromHandToTable(table, hand, src, dst):
assert type(dst) is int
assert type(src) is int
in_play = table.cards[dst]
to_move = hand.cards[src]
hcards = hand.cards[:src] + hand.cards[src+1:]
assert len(hcards) == len(hand.cards) - 1
assert type(to_move) is Card
assert type(in_play) is TaggedCards or in_play == []
idx = table.cards.index(in_play)
news = []
news = table.cards[:dst] + table.cards[dst+1:] + [TaggedCards(table.cards[dst].cards + [to_move])]
newTable = Table(news)
assert len(newTable.flatten()) + len(hcards) == len(hand.cards) + len(table.flatten()), fuck()
return newTable, Hand(hcards)
def removeFromTcards(t, to_move):
# tmp = []
# for j, c in enumerate(t.cards):
# if c == to_move:
# break
# tmp.append(c)
# tmp.extend(t.cards[j+1:])
# return tmp
cards = copy(t.cards)
cards.remove(to_move)
return cards
def fromTableToEmpty(table, hand, src, to_move):
assert type(src) is tuple # TODO: unused src[1], even in other TableToTable
in_play = []
tpos, cpos = src
hcards = hand.cards
assert type(src[0]) is int
assert type(to_move) is Card
news = [TaggedCards([to_move])]
for i, t in enumerate(table.cards):
if tpos == i:
tmp = removeFromTcards(t, to_move)
if tmp != []:
news.append(TaggedCards(tmp))
else: else:
news.append(t) news.append(t)
return Table(news), Hand(hcards) newTable = Table(news)
assert len(newTable.flatten()) + len(hcards) == len(hand.cards) + len(table.flatten()), fuck()
return newTable, Hand(hcards)
def fromTableToTable(table, hand, src, dst, to_move):
assert type(src) is tuple
in_play = table.cards[dst]
tpos, cpos = src
# to_move = table.cards[tpos].cards[cpos]
hcards = hand.cards
assert type(to_move) is Card
assert type(in_play) is TaggedCards
news = []
rimpiazzata = False
for i, t in enumerate(table.cards):
if i == dst:
p = TaggedCards(in_play.cards + [to_move])
news.append(p)
elif tpos == i:
tmp = removeFromTcards(t, to_move)
if tmp != []:
news.append(TaggedCards(tmp))
else:
news.append(t)
newTable = Table(news)
assert len(newTable.flatten()) + len(hcards) == len(hand.cards) + len(table.flatten()), fuck()
return newTable, Hand(hcards)

View file

@ -30,7 +30,7 @@ class WColoredButton(WButton):
return r return r
def handle_key(self, inp): def handle_key(self, inp):
if inp in [KEY_ENTER, b's', b'd', b'm']: if inp in [KEY_ENTER, b's', b'd', b'm', b'p']:
return inp return inp
pass pass
@ -46,7 +46,7 @@ class WColoredFrame(WFrame):
self.color = color self.color = color
def handle_key(self, inp): def handle_key(self, inp):
if inp in [KEY_ENTER, b's', b'd', b'm']: if inp in [KEY_ENTER, b's', b'd', b'm', b'p']:
return inp return inp
pass pass
@ -91,7 +91,7 @@ class WCardRadioButton(WRadioButton):
self.id = id self.id = id
def handle_key(self, inp): def handle_key(self, inp):
if inp in [KEY_ENTER, b's', b'd', b'm']: if inp in [KEY_ENTER, b's', b'd', b'm', b'p']:
return inp return inp
pass pass