ono_sendai - wip

This commit is contained in:
Francesco Mecca 2019-08-19 00:12:42 +02:00
parent b93521988b
commit 8c143abff0
15 changed files with 310 additions and 87 deletions

View file

@ -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)

View file

@ -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)

View file

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

View file

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

View file

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

View file

@ -19,4 +19,5 @@
▀B╨╜╜≡▄▄╠╩╝╨╨"` ,H╫╫╫╫╫▀ ╙▒╫Ñ╫╩▌""╨╨╩╩▄▄╗≡╜╜VQ▀
` .╬]╫╫╫╫╛ ╙▓╫╫N╨╫⌐ `
"╩Ñ╣▀ ╙ÑÑ"
LOADING...

View file

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

View file

@ -7,11 +7,12 @@ from os import system
frames = []
for i in range(5):
with open(str(i)+'.txt', 'r') as f:
with open('animation/'+str(i)+'.txt', 'r') as f:
content = f.read()
frames.append(f'{Fore.MAGENTA}'+content+f'{Style.RESET_ALL}')
def animate(n):
system('clear')
for i in range(n):
print(frames[i%5])
sleep(0.2)

View file

@ -1,4 +0,0 @@
from colorama import Style,Fore
from symbols import *
print(big['hat'] + n + big['clovers'] + n + big[1] + n + clovers[2] + n + clovers[3] + n)

View file

@ -1,25 +0,0 @@
___
❘♠ ❘
❘ ̲̲ ̲2̲❘
❘♠̲̲ ̲1̲❘
❘♠̲̲ ̲K̲❘
___
❘♦ ❘
❘ ̲̲ ̲3̲❘
❘♦̲̲ ̲4̲❘
❘♦̲̲ ̲5̲❘
❘♦̲̲ ̲6̲❘
❘♦̲̲ ̲7̲❘
❘♦̲̲ ̲8̲❘
❘♦̲̲ ̲9̲❘
❘♦̲̲1̲0̲❘
___
❘♥ ❘
❘ ̲̲ ̲8̲❘
❘♥̲̲ ̲9̲❘
❘♥̲̲ ̲Q̲❘
___
❘♣ ❘
❘ ̲̲ ̲4̲❘
❘♣̲̲ ̲5̲❘
❘♣̲̲ ̲6̲❘

23
ono_sendai/demo.py Normal file
View file

@ -0,0 +1,23 @@
self.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)
# ]))

View file

@ -2,12 +2,16 @@ from picotui.context import Context
from picotui.screen import Screen
from time import sleep
import os
from widgets import *
import state
action = ''
exit = False
ID = "tui"
game = state.State([ID, "bot1"])
class FrameFactory:
titles = ['0x10', '0x11', '0x12', '0x13', '0x14', '0x15', '0x16', '0x17',
@ -85,7 +89,7 @@ class FrameFactory:
def newHandFrame(self, cards):
assert type(cards) is list, type(cards)
h = 27 # height ?
self.d.add(1, 1, WColoredFrame(12, h, 'HAND', blue))
self.d.add(1, 1, WColoredFrame(12, h, 'HAND: '+str(len(cards)), blue))
coloredCards = [f'{Fore.BLUE}'+cards[0]] + cards[1:-1] + [cards[-1]+f'{Style.RESET_ALL}']
w = WCardRadioButton(coloredCards, -1, self.constrainAllWidgets, isHand=True)
self.d.add(2, 2, w)
@ -151,9 +155,36 @@ def makeButtons(d):
global action ; action = "BACK"
buttonback.on_click = doBack
def wrong_play():
from sys import stdout
os.system('clear')
print(f'{Fore.RED}'+'Wrong play. Retry...'+f'{Style.RESET_ALL}')
sleep(2)
def make_auto_move():
import sys
from animation.octopus import animate
pid = os.fork()
if pid == 0:
# child
os.system('sleep 1')
os.system('echo DRAW')
sys.exit()
else:
p = os.waitpid(pid, os.WNOHANG)
while p == (0, 0):
animate(10)
p = os.waitpid(pid, os.WNOHANG)
game.draw()
game.next_turn()
game.next_turn()
while not exit:
table, hand = state.next()
while game.cur_player != ID:
make_auto_move()
table, hand = game.last()
with Context():
Screen.attr_color(C_WHITE, C_GREEN)
@ -179,15 +210,20 @@ while not exit:
exit = True
elif action == 'MOVE':
# TODO: transition effect
state.update_table(table, hand, *f.getChoices()) # get them from next
game.advance(*f.getChoices()) # get them from next
elif action == 'DRAW':
pass
game.draw()
game.next_turn()
elif action == 'RESET':
while state.size() > 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

View file

@ -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

View file

@ -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̲❘',