ono_sendai - wip
This commit is contained in:
parent
b93521988b
commit
8c143abff0
15 changed files with 310 additions and 87 deletions
|
@ -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)
|
||||
|
|
156
metro_holografix/scrapes/cardtypes.py
Normal file
156
metro_holografix/scrapes/cardtypes.py
Normal 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)
|
|
@ -20,3 +20,4 @@
|
|||
|
||||
|
||||
|
||||
LOADING...
|
||||
|
|
|
@ -20,3 +20,4 @@
|
|||
Φ╚╫╫╫╫` ▀╬╫N╨▌
|
||||
▒╩╫╫╫▌ ▀╫╫╧*
|
||||
|
||||
LOADING...
|
||||
|
|
|
@ -20,3 +20,4 @@
|
|||
"╩Ñ╬▌ ╙ÑÑ╨`
|
||||
|
||||
|
||||
LOADING...
|
||||
|
|
|
@ -19,4 +19,5 @@
|
|||
▀B╨╜╜≡▄▄╠╩╝╨╨"` ,H╫╫╫╫╫▀ ╙▒╫Ñ╫╩▌""╨╨╩╩▄▄╗≡╜╜VQ▀
|
||||
` .╬]╫╫╫╫╛ ╙▓╫╫N╨╫⌐ `
|
||||
"╩Ñ╣▀ ╙ÑÑ"
|
||||
|
||||
|
||||
LOADING...
|
||||
|
|
|
@ -20,3 +20,4 @@
|
|||
'╝╨'"╜▀ßM^` ▒╨╫╫╫╫⌐ ▀╬╫Ñ╙╫⌐ └╝╧╙└` ╜┘
|
||||
"╩ÑÑ╩ ▀ÑÑ"`
|
||||
|
||||
LOADING...
|
||||
|
|
BIN
ono_sendai/animation/__pycache__/octopus.cpython-36.pyc
Normal file
BIN
ono_sendai/animation/__pycache__/octopus.cpython-36.pyc
Normal file
Binary file not shown.
|
@ -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)
|
|
@ -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)
|
|
@ -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
23
ono_sendai/demo.py
Normal 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)
|
||||
# ]))
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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̲❘',
|
||||
|
|
Loading…
Reference in a new issue