From 8c143abff074d455d634c0df1fb0a640fb8a5f13 Mon Sep 17 00:00:00 2001 From: Francesco Mecca Date: Mon, 19 Aug 2019 00:12:42 +0200 Subject: [PATCH] ono_sendai - wip --- metro_holografix/cardtypes.py | 6 +- metro_holografix/scrapes/cardtypes.py | 156 ++++++++++++++++++ ono_sendai/animation/0.txt | 1 + ono_sendai/animation/1.txt | 1 + ono_sendai/animation/2.txt | 1 + ono_sendai/animation/3.txt | 3 +- ono_sendai/animation/4.txt | 1 + .../__pycache__/octopus.cpython-36.pyc | Bin 0 -> 753 bytes ono_sendai/animation/{prova.py => octopus.py} | 3 +- ono_sendai/broker.py | 4 - ono_sendai/cards | 25 --- ono_sendai/demo.py | 23 +++ ono_sendai/prova.py | 52 +++++- ono_sendai/state.py | 113 ++++++++----- ono_sendai/symbols.py | 8 +- 15 files changed, 310 insertions(+), 87 deletions(-) create mode 100644 metro_holografix/scrapes/cardtypes.py create mode 100644 ono_sendai/animation/__pycache__/octopus.cpython-36.pyc rename ono_sendai/animation/{prova.py => octopus.py} (84%) delete mode 100644 ono_sendai/broker.py delete mode 100644 ono_sendai/cards create mode 100644 ono_sendai/demo.py diff --git a/metro_holografix/cardtypes.py b/metro_holografix/cardtypes.py index 40bd55b..44a2eed 100644 --- a/metro_holografix/cardtypes.py +++ b/metro_holografix/cardtypes.py @@ -32,7 +32,7 @@ class TaggedCards: return self.cards.__iter__() def __eq__(self, other): - assert type(other) is type(self) + assert type(other) is type(self), type(other) if len(other.cards) != len(self.cards) or self.tag != other.tag or self.tipo != other.tipo: return False else: @@ -53,7 +53,6 @@ class TaggedCards: return False class Tavolo: - cards = list() # lista di taggedcards def __init__(self, cs): assert type(cs) is list self.cards = cs @@ -83,6 +82,9 @@ class Tavolo: def punteggio(self): return len(self.getValide()) - len(self.getNonValide()) + def singles(self): + return [c for c in self.cards if c.tipo == 'Singolo'] + # old ocaml work def flatten(lst): return sorted([s for subl in lst for s in subl], key=lambda x: x.value) diff --git a/metro_holografix/scrapes/cardtypes.py b/metro_holografix/scrapes/cardtypes.py new file mode 100644 index 0000000..40bd55b --- /dev/null +++ b/metro_holografix/scrapes/cardtypes.py @@ -0,0 +1,156 @@ +from collections import namedtuple; + +Card = namedtuple('Card', 'seed value') + +class Mano: + cards = list() # lista di cards + def __init__(self, carte): + assert type(carte) is list and type(carte[0]) is Card + self.cards = carte # lista di Carte + +class TaggedCards: + cards = None + tag = '' + tipo = '' + def __init__(self, carte): + assert type(carte) is list and type(carte[0]) is Card + self.cards = list(sorted(carte, key=lambda x: str(x))) # lista di Carte + self.tag = 'NonValido' if not is_valida(self.cards) else 'Valido' + self.tipo = 'Singolo' if len(carte) == 1 else 'Tris' if is_tris(carte) else 'Scala' + + def __hash__(self): + import functools + def cmp(c1, c2): + return c1.value < c2.value if c1.seed == c2.seed else c1.seed < c2.seed + lst = tuple(sorted(self.cards, key=functools.cmp_to_key(cmp))) + return hash(lst) + + def __repr__(self): + return "TaggedCards<%s, %s, %s>" % (self.cards, self.tag, self.tipo) + + def __iter__(self): + return self.cards.__iter__() + + def __eq__(self, other): + assert type(other) is type(self) + if len(other.cards) != len(self.cards) or self.tag != other.tag or self.tipo != other.tipo: + return False + else: + return set(self.cards) == set(other.cards) + + def __gt__(self, other): + if self.tipo == 'Tris' and len(self.cards) == 4: + return False + if other.tipo == 'Tris' and len(other.cards) == 4: + return True + elif self.tipo != 'Singolo' and other.tipo == 'Singolo': + return True + elif self.tipo == 'Singolo' and other.tipo != 'Singolo': + return False + elif self.tag == 'NonValido' and other.tag == 'Valido': + return True + else: + return False + +class Tavolo: + cards = list() # lista di taggedcards + def __init__(self, cs): + assert type(cs) is list + self.cards = cs + + def __hash__(self): + return sum([c.__hash__() for c in self.cards]) + + def __repr__(self): + return "Tavolo<%s>" % (self.cards,) + + def getNonValide(self): + assert type(self.cards[0]) is TaggedCards + f = [c for c in self.cards if c.tag == 'NonValido'] + return f + + def getValide(self): + assert type(self.cards[0]) is TaggedCards + f = [c for c in self.cards if c.tag == 'Valido'] + return f + + def getAll(self): + return self.cards + + def llen(self): + return len(flatten(self.getAll())) + + def punteggio(self): + return len(self.getValide()) - len(self.getNonValide()) + +# old ocaml work +def flatten(lst): + return sorted([s for subl in lst for s in subl], key=lambda x: x.value) + +def no_double_seed(carte): + seeds = set([c.seed for c in carte]) + return len(seeds) == len(carte) + +def is_only_one_seed(carte): + seeds = set([c.seed for c in carte]) + return len(seeds) == 1 + +def no_double_value(carte): + seeds = set([c.value for c in carte]) + return len(seeds) == len(carte) + +def is_tris(carte): + values = set([c.value for c in carte]) + if len(values) == 1: + return no_double_seed(carte) + else: + return False + +def split(values, accum=[]): + a = values[0] + if len(values) > 2: + b = values[1] + if a == b - 1: + return split(values[1:], accum + [a]) + else: + return accum + [a], values[1:] + else: + return accum + [a], values[1:] + +def is_straight(carte): + assert type(carte) is list and type(carte[0]) is Card + def _is_straight(carte): + if len(carte) == 1: + return True + elif len(carte) == 0: + assert False + else: + a = carte[0] + b = carte[1] + if a == b - 1: + return _is_straight(carte[1:]) + else: + return False + + if not (no_double_value(carte) and is_only_one_seed(carte)): + return False + else: + values = [v for s, v in sorted(carte, key=lambda x:x.value)] + first, last = values[0], values[-1] + if last == 13 and first == 1: + head, tail = split(values) + return _is_straight(head) and _is_straight(tail) + else: + return _is_straight(values) + +def is_valida(carte): + carte = list(sorted(carte, key = lambda x : x[1])) + if len(carte) < 3: + return False + else: + a = carte[0][1] + b = carte[1][1] + if a == b: + return is_tris(carte) + else: + return is_straight(carte) diff --git a/ono_sendai/animation/0.txt b/ono_sendai/animation/0.txt index 57414c0..82698f9 100644 --- a/ono_sendai/animation/0.txt +++ b/ono_sendai/animation/0.txt @@ -20,3 +20,4 @@ +LOADING... diff --git a/ono_sendai/animation/1.txt b/ono_sendai/animation/1.txt index c2bea6c..407f903 100644 --- a/ono_sendai/animation/1.txt +++ b/ono_sendai/animation/1.txt @@ -20,3 +20,4 @@ Φ╚╫╫╫╫` ▀╬╫N╨▌ ▒╩╫╫╫▌ ▀╫╫╧* +LOADING... diff --git a/ono_sendai/animation/2.txt b/ono_sendai/animation/2.txt index 1236383..ee986f5 100644 --- a/ono_sendai/animation/2.txt +++ b/ono_sendai/animation/2.txt @@ -20,3 +20,4 @@ "╩Ñ╬▌ ╙ÑÑ╨` +LOADING... diff --git a/ono_sendai/animation/3.txt b/ono_sendai/animation/3.txt index a4607d2..462f18b 100644 --- a/ono_sendai/animation/3.txt +++ b/ono_sendai/animation/3.txt @@ -19,4 +19,5 @@ ▀B╨╜╜≡▄▄╠╩╝╨╨"` ,H╫╫╫╫╫▀ ╙▒╫Ñ╫╩▌""╨╨╩╩▄▄╗≡╜╜VQ▀ ` .╬]╫╫╫╫╛ ╙▓╫╫N╨╫⌐ ` "╩Ñ╣▀ ╙ÑÑ" - + +LOADING... diff --git a/ono_sendai/animation/4.txt b/ono_sendai/animation/4.txt index da8cc4b..2844d0a 100644 --- a/ono_sendai/animation/4.txt +++ b/ono_sendai/animation/4.txt @@ -20,3 +20,4 @@ '╝╨'"╜▀ßM^` ▒╨╫╫╫╫⌐ ▀╬╫Ñ╙╫⌐ └╝╧╙└` ╜┘ "╩ÑÑ╩ ▀ÑÑ"` +LOADING... diff --git a/ono_sendai/animation/__pycache__/octopus.cpython-36.pyc b/ono_sendai/animation/__pycache__/octopus.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe60c5376af7b6c124eb991938279beb105f45a9 GIT binary patch literal 753 zcmYjPJ#Q015S_UX`|Q|`F(ihDipB*o5)u^(L=d0|kw_u|Cq<`|cVf=m-ClM#D2_s9 zdTPioprPPjAX=(zp~+vMV)j6gk@ns0&b!_Bp7wUP+y43O<^FdB_yHGciRbru=r0Tc z1m;j+jD;6_=+<8D7eO48v)(s=ihP!5-lMNn8MI*GK&WS3XH1u2>D$YZu zowU<3D^ioma(oi3nPX#7ZBICpx;#cld%#1lGZ@ap-E@4*;3?nAUT?fb;~D=Hg|`Y$ z34#fPUw{9y4+rc6SX;1d!%0r5QVl+A`tgISulGiwa<|w}rR9`tSgEWuwsD}+g0u>_ z#dff?n0*4(5S2jwLBF)Mq;e3KrP2Zfm2u4F2O=K=vN2**F%6H_zWChi-tS5CXUAb4IS`NB3 zMOIW=UmIodzy^v^VVe_K8gj 1: - state.prev() + while game.size() > 1: + game.backtrack() elif action == 'SEND': - pass + try: + game.done() + game.next_turn() + except state.WrongMoveException as e: + wrong_play() elif action == 'BACK': - state.prev() + game.backtrack() else: assert False diff --git a/ono_sendai/state.py b/ono_sendai/state.py index 3cb440e..b74585a 100644 --- a/ono_sendai/state.py +++ b/ono_sendai/state.py @@ -1,15 +1,18 @@ import sys sys.path.append('../') import json +from copy import deepcopy as copy +from functools import cmp_to_key + +from IPython import embed as fuck from metro_holografix.cardtypes import * import symbols as sym -Hand = Tavolo class Table(Tavolo): def is_valid(self): - return len(self.getNonValide()) == 0 + return len(self.singles()) == 0 and len(self.getNonValide()) == 0 def widget_repr(self): for ts in self.cards: @@ -25,7 +28,9 @@ class Table(Tavolo): class Hand: def __init__(self, cards): - self.cards = cards + def sortc(a, b): + return -1 if (a[1],a[0]) < (b[1],b[0]) else 1 + self.cards = list(sorted(cards, key=cmp_to_key(sortc))) def widget_repr(self): yi = [sym.big['hat']] @@ -36,31 +41,70 @@ class Hand: seed = card[0].lower() yi.append(sym.sym[seed][card[1]]) return yi - -events = [ # list of tuples table-hand - (Table([ - TaggedCards([ - Card("Pikes", 2), - Card("Clovers", 2), - Card("Tiles", 2), - Card("Hearts", 2)]), - TaggedCards([ - Card("Hearts", 1), - Card("Clovers", 1), - Card("Pikes", 1), - Card("Tiles", 1)]), - ]), Hand([ - Card("Pikes", 12), - Card("Clovers", 12), - Card("Tiles", 12), - Card("Hearts", 12), - Card("Hearts", 13), - Card("Clovers", 13), - Card("Pikes", 13), - Card("Tiles", 13) - ])) -] +def make_deck(): + from random import shuffle # TODO: mersenne + def make_set(seed): + for i in range(1, 14): + yield Card(seed, i) + odeck = [m for seed in ['Pikes', 'Hearts', 'Clovers', 'Tiles'] for m in make_set(seed)] + shuffle(odeck) + return odeck + +class WrongMoveException(Exception): + pass + +class State: + def __init__(self, ids): + self.deck = make_deck() + self.players = dict() + self.table = Table([]) + self.round = None + self.ids = ids + self.cur_player = ids[0] + for i in ids: + cards = [self.deck.pop() for i in range(11)] + self.players[i] = Hand(cards) + + def draw(self): + hand = self.players[self.cur_player] + nhand = Hand(hand.cards + [self.deck.pop()]) + self.players[self.cur_player] = nhand + self.round = None + + def next_turn(self): + assert self.round is None + next_player = self.ids[(self.ids.index(self.cur_player) + 1) % len(self.ids)] + self.cur_player = next_player + self.round = [(copy(self.table), copy(self.players[self.cur_player]))] + + def done(self): + assert self.round is not None + original = self.table + table, hand = self.last() + if not table.is_valid() or len(set(original.cards) - set(table.cards)) != 0: + raise WrongMoveException() + else: + self.table, self.players[self.cur_player] = table, hand + self.round = None + + def last(self): + return self.round[-1] + + def backtrack(self): + if len(self.round) >= 2: + return self.round.pop() + else: + return self.round[0] + + def size(self): + return len(self.round) + + def advance(self, src, dst): + table, hand = self.last() + t, h = gioca(table, hand, src, dst) + self.round.append((t, h)) + return t, h def fromJson(j): hcards = [Card(seed, value) for seed, value in j['hand']] @@ -77,17 +121,6 @@ def toJson(table, hand): j['table'].append(tc.cards) return json.dumps(j) -def next(): - return events[-1] - -def prev(): - if len(events) >= 2: - return events.pop() - else: - return events[0] - -def size(): - return len(events) # TODO: refactor language def gioca(tavolo, hand, src, dst): @@ -116,7 +149,3 @@ def gioca(tavolo, hand, src, dst): news.append(t) return Table(news), Hand(hcards) -def update_table(table, hand, src, dst): - t, h = gioca(table, hand, src, dst) - events.append((t, h)) - return t, h diff --git a/ono_sendai/symbols.py b/ono_sendai/symbols.py index 1b0f5c7..8b52dc1 100644 --- a/ono_sendai/symbols.py +++ b/ono_sendai/symbols.py @@ -7,7 +7,7 @@ pikes = { 6: '❘♠̲̲ ̲6̲❘', 7: '❘♠̲̲ ̲7̲❘', 8: '❘♠̲̲ ̲8̲❘', - 8: '❘♠̲̲ ̲9̲❘', + 9: '❘♠̲̲ ̲9̲❘', 10: '❘♠̲̲1̲0̲❘', 11: '❘♠̲̲ ̲J̲❘', 12: '❘♠̲̲ ̲Q̲❘', @@ -23,7 +23,7 @@ clovers = { 6: '❘♣̲̲ ̲6̲❘', 7: '❘♣̲̲ ̲7̲❘', 8: '❘♣̲̲ ̲8̲❘', - 8: '❘♣̲̲ ̲9̲❘', + 9: '❘♣̲̲ ̲9̲❘', 10: '❘♣̲̲1̲0̲❘', 11: '❘♣̲̲ ̲J̲❘', 12: '❘♣̲̲ ̲Q̲❘', @@ -39,7 +39,7 @@ hearts = { 6: '❘♥̲̲ ̲6̲❘', 7: '❘♥̲̲ ̲7̲❘', 8: '❘♥̲̲ ̲8̲❘', - 8: '❘♥̲̲ ̲9̲❘', + 9: '❘♥̲̲ ̲9̲❘', 10: '❘♥̲̲1̲0̲❘', 11: '❘♥̲̲ ̲J̲❘', 12: '❘♥̲̲ ̲Q̲❘', @@ -55,7 +55,7 @@ tiles = { 6: '❘♦̲̲ ̲6̲❘', 7: '❘♦̲̲ ̲7̲❘', 8: '❘♦̲̲ ̲8̲❘', - 8: '❘♦̲̲ ̲9̲❘', + 9: '❘♦̲̲ ̲9̲❘', 10: '❘♦̲̲1̲0̲❘', 11: '❘♦̲̲ ̲J̲❘', 12: '❘♦̲̲ ̲Q̲❘',