Octopus_Carnival/ono_sendai/state.py

186 lines
5.7 KiB
Python
Raw Normal View History

2019-08-17 17:40:16 +02:00
import sys
sys.path.append('../')
2019-08-18 17:19:11 +02:00
import json
2019-08-19 00:12:42 +02:00
from copy import deepcopy as copy
from functools import cmp_to_key
from IPython import embed as fuck
2019-08-18 17:19:11 +02:00
2019-08-17 17:40:16 +02:00
from metro_holografix.cardtypes import *
import symbols as sym
class Table(Tavolo):
def is_valid(self):
2019-08-19 18:24:38 +02:00
return len(self.cards) == 0 or (len(self.singles()) == 0 and len(self.getNonValide()) == 0)
def flatten(self):
return [c for tc in self.cards for c in tc.cards]
2019-08-17 17:40:16 +02:00
def widget_repr(self):
for ts in self.cards:
2019-08-20 16:39:33 +02:00
ocards = list(sorted(ts.cards, key=lambda c: c.value))
2019-08-17 17:40:16 +02:00
yi = [sym.big['hat']]
2019-08-20 16:39:33 +02:00
seed = ocards[0][0].lower()
2019-08-17 17:40:16 +02:00
yi.append(sym.big[seed])
2019-08-20 16:39:33 +02:00
yi.append(sym.big[ocards[0][1]])
for card in ocards[1:]:
2019-08-17 17:40:16 +02:00
seed = card[0].lower()
yi.append(sym.sym[seed][card[1]])
yield yi
2019-08-19 18:24:38 +02:00
def equality(self, other):
b = set(other.flatten())
a = set(self.flatten())
gt = a - b
lt = b - a
if gt == lt and lt == set():
return True
else:
return False
2019-08-17 18:21:18 +02:00
class Hand:
def __init__(self, cards):
2019-08-19 00:12:42 +02:00
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)))
2019-08-17 18:21:18 +02:00
2019-08-20 16:39:33 +02:00
def __repr__(self):
return 'Hand<'+ str(self.cards) + '>'
2019-08-17 18:21:18 +02:00
def widget_repr(self):
yi = [sym.big['hat']]
seed = self.cards[0][0].lower()
yi.append(sym.big[seed])
yi.append(sym.big[self.cards[0][1]])
for card in self.cards[1:]:
seed = card[0].lower()
yi.append(sym.sym[seed][card[1]])
return yi
2019-08-19 00:12:42 +02:00
def make_deck():
from random import shuffle # TODO: mersenne
def make_set(seed):
for i in range(1, 14):
yield Card(seed, i)
2019-08-20 16:39:33 +02:00
odeck = [m for seed in ['Pikes', 'Hearts', 'Clovers', 'Tiles'] for m in make_set(seed)] * 2
2019-08-19 00:12:42 +02:00
shuffle(odeck)
2019-08-20 16:39:33 +02:00
assert len(odeck) == 104
2019-08-19 00:12:42 +02:00
return odeck
class WrongMoveException(Exception):
pass
class State:
def __init__(self, ids):
self.deck = make_deck()
2019-08-19 18:24:38 +02:00
self.winner = None
self.hasEnded = False
2019-08-19 00:12:42 +02:00
self.players = dict()
self.table = Table([])
2019-08-20 16:39:33 +02:00
self.turn = None
2019-08-19 00:12:42 +02:00
self.ids = ids
self.cur_player = ids[0]
2019-08-20 16:39:33 +02:00
self.nrounds = 0
2019-08-19 00:12:42 +02:00
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
2019-08-19 18:24:38 +02:00
assert len(self.players[self.cur_player].cards) == len(hand.cards) + 1
2019-08-20 16:39:33 +02:00
self.turn = None
2019-08-19 00:12:42 +02:00
def next_turn(self):
2019-08-20 16:39:33 +02:00
assert self.turn is None
2019-08-19 00:12:42 +02:00
next_player = self.ids[(self.ids.index(self.cur_player) + 1) % len(self.ids)]
self.cur_player = next_player
2019-08-20 16:39:33 +02:00
self.turn = [(copy(self.table), copy(self.players[self.cur_player]))]
self.nrounds = self.nrounds + 1 if self.cur_player == self.ids[0] else self.nrounds
2019-08-19 00:12:42 +02:00
def done(self):
2019-08-20 16:39:33 +02:00
assert self.turn is not None
2019-08-19 00:12:42 +02:00
original = self.table
table, hand = self.last()
2019-08-20 16:39:33 +02:00
if original.equality(table):
raise WrongMoveException()
elif not table.is_valid() or len(set(original.flatten()) - set(table.flatten())) != 0:
if self.cur_player != 'you':
fuck() # debug
2019-08-19 00:12:42 +02:00
raise WrongMoveException()
else:
self.table, self.players[self.cur_player] = table, hand
2019-08-20 16:39:33 +02:00
self.turn = None
2019-08-19 18:24:38 +02:00
if len(hand.cards) == 0:
# won
self.hasEnded = True
self.winner = self.cur_player
2019-08-19 00:12:42 +02:00
def last(self):
2019-08-20 16:39:33 +02:00
return self.turn[-1]
2019-08-19 00:12:42 +02:00
def backtrack(self):
2019-08-20 16:39:33 +02:00
if len(self.turn) >= 2:
return self.turn.pop()
2019-08-19 00:12:42 +02:00
else:
2019-08-20 16:39:33 +02:00
return self.turn[0]
2019-08-19 00:12:42 +02:00
def size(self):
2019-08-20 16:39:33 +02:00
return len(self.turn)
2019-08-19 00:12:42 +02:00
2019-08-19 18:24:38 +02:00
def move_and_advance(self, src, dst):
2019-08-19 00:12:42 +02:00
table, hand = self.last()
t, h = gioca(table, hand, src, dst)
2019-08-20 16:39:33 +02:00
self.turn.append((t, h))
2019-08-19 00:12:42 +02:00
return t, h
2019-08-18 17:19:11 +02:00
2019-08-19 18:24:38 +02:00
def advance(self, table, hand):
2019-08-20 16:39:33 +02:00
self.turn.append((table, hand))
2019-08-19 18:24:38 +02:00
return table, hand
2019-08-18 17:19:11 +02:00
def fromJson(j):
hcards = [Card(seed, value) for seed, value in j['hand']]
tcards = []
for tc in j['table']:
tcards.append(TaggedCards([Card(seed, value) for seed, value in tc]))
return Table(tcards), Hand(hcards)
def toJson(table, hand):
j = dict()
j['hand'] = hand.cards
j['table'] = []
for tc in table.cards:
j['table'].append(tc.cards)
return json.dumps(j)
2019-08-17 17:40:16 +02:00
# TODO: refactor language
2019-08-17 18:21:18 +02:00
def gioca(tavolo, hand, src, dst):
2019-08-17 17:40:16 +02:00
giocata = [] if dst == 'Empty' else tavolo.cards[dst]
2019-08-17 18:21:18 +02:00
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
2019-08-20 16:39:33 +02:00
assert src[0] != 'Hand' or len(hcards) == len(hand.cards) - 1
2019-08-17 18:21:18 +02:00
assert type(dst) is int or dst == 'Empty'
assert type(src[0]) is int or src[0] == 'Hand'
2019-08-17 17:40:16 +02:00
assert type(da_muovere) is Card
assert type(giocata) is TaggedCards or giocata == []
2019-08-17 18:21:18 +02:00
2019-08-17 17:40:16 +02:00
idx = -1 if dst == 'Empty' else tavolo.cards.index(giocata)
2019-08-17 18:21:18 +02:00
news = [TaggedCards([da_muovere])] if type(giocata) is list else []
2019-08-17 17:40:16 +02:00
rimpiazzata = False
for i, t in enumerate(tavolo.cards):
if i == idx:
p = TaggedCards(giocata.cards + [da_muovere])
news.append(p)
elif not rimpiazzata and da_muovere in t.cards:
t = [c for c in t.cards if c != da_muovere]
if t != []:
news.append(TaggedCards(t))
rimpiazzata = True
else:
news.append(t)
2019-08-17 18:21:18 +02:00
return Table(news), Hand(hcards)