This commit is contained in:
Francesco Mecca 2019-08-19 18:24:38 +02:00
parent 29834696e0
commit 3beaec0cfd
8 changed files with 135 additions and 37 deletions

View file

@ -16,6 +16,14 @@ let card_type_to_string = function
| Pikes-> "Pikes"
| Nothing-> "Nothing"
let string_to_card_type = function
| "Hearts" -> Hearts
| "Tiles" -> Tiles
| "Clovers" -> Clovers
| "Pikes" -> Pikes
| "Nothing" -> Nothing
| _ -> assert false
type card = { seed: card_type ; value: int }
let make seed value =

View file

@ -1,4 +1,4 @@
(executable
(name main)
(libraries core)
(libraries core yojson)
)

View file

@ -1 +0,0 @@
open Yojson;;

View file

@ -4,4 +4,34 @@
una volta vista la mano, rimuovi le carte inusabili nel turno;
considerata una carta giocabile in mano, considera le carte "prossime", bruteforce;
*)
open Printer;;
open Yojson.Basic.Util;;
let read_json () =
let json = Yojson.Basic.from_channel stdin in let open Yojson.Basic.Util in
let make_card l =
let hd = List.hd l |> to_string in
let tl = List.tl l |> List.hd |> to_int in
Cards.make (Cards.string_to_card_type hd) tl in
let hand = json |> member "hand" |> to_list |>
List.map (fun c -> [ c |> to_list |> make_card ] |> Tcards.make) in (* List of tcards `singles *)
let table = json |> member "table" |> to_list |>
List.map (fun l -> to_list l |> List.map (fun cl -> cl |> to_list |> make_card) |> Tcards.make)
|> Table.make
in
(hand, table)
let to_json (table:Table.table) =
let cards_to_json (cards:Cards.card list) =
`List (List.map (fun (c:Cards.card) -> `List [`String (c.seed |> Cards.card_type_to_string); `Int c.value]) cards) in
let tcards_to_json (tc:Tcards.tcards) =
cards_to_json tc.cards in
`List (List.map (fun tcl -> tcards_to_json tcl) table.cards);;
let open Yojson.Basic.Util in
let hand, table = read_json () in
let tn = Table.make (table.cards@hand) in
let res, _ = Table.alg ~maxiter:14 tn void_printer in
(* Printf.printf "%a\n" print_table res;; *)
to_json res |> Yojson.Basic.to_channel stdout

1
ono_sendai/demo.json Normal file
View file

@ -0,0 +1 @@
{"hand": [["Clovers", 12], ["Hearts", 12], ["Pikes", 12], ["Tiles", 12], ["Clovers", 13], ["Hearts", 13], ["Pikes", 13], ["Tiles", 13]], "table": [[["Clovers", 2], ["Hearts", 2], ["Pikes", 2], ["Tiles", 2]], [["Clovers", 1], ["Hearts", 1], ["Pikes", 1], ["Tiles", 1]]]}

View file

@ -1,23 +0,0 @@
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

@ -3,15 +3,18 @@ from picotui.screen import Screen
from time import sleep
import os
import json
from widgets import *
from state import Table, Hand
from metro_holografix.cardtypes import *
import state
action = ''
exit = False
ID = "tui"
game = state.State([ID, "bot1"])
game = state.State(["bot1", ID])
class FrameFactory:
titles = ['0x10', '0x11', '0x12', '0x13', '0x14', '0x15', '0x16', '0x17',
@ -161,32 +164,76 @@ def wrong_play():
print(f'{Fore.RED}'+'Wrong play. Retry...'+f'{Style.RESET_ALL}')
sleep(2)
def make_auto_move():
def spawn_and_wait(str):
import sys
from subprocess import PIPE, Popen
from animation.octopus import animate
r, w = os.pipe()
pid = os.fork()
if pid == 0:
# child
os.system('sleep 1')
os.system('echo DRAW')
os.close(r)
res = Popen(["../hosaka/_build/default/main.exe"], stdout=PIPE, stdin=PIPE)
out, err = res.communicate(str.encode('utf-8'))
res.stdin.close()
w = os.fdopen(w, 'w')
w.write(out.decode('utf-8'))
sys.exit()
else:
os.close(w)
p = os.waitpid(pid, os.WNOHANG)
while p == (0, 0):
animate(10)
p = os.waitpid(pid, os.WNOHANG)
r = os.fdopen(r)
output = r.read()
return output
def validate_auto_play(original, nl):
# nl is a nested list of taggedcards, but without type
# must reconstruct
def make_cards(l):
return Card(*l)
pp = []
for ts in nl:
pp.append(TaggedCards([make_cards(cl) for cl in ts]))
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'])
assert len(table.cards) == 0 or table.is_valid()
if original.equality(table) == True:
return 'DRAW'
else:
return table, hand
def make_auto_move(original, game):
table, hand = game.last()
tstr = state.toJson(table, hand)
output = spawn_and_wait(tstr)
res = validate_auto_play(original, json.loads(output))
if type(res) is str:
game.draw()
game.next_turn()
elif type(res) is tuple:
game.advance(*res)
game.done()
else:
assert False, type(res)
game.next_turn()
game.next_turn()
while not exit:
while not exit and not game.hasEnded:
while game.cur_player != ID:
make_auto_move()
make_auto_move(game.last()[0], game)
if game.hasEnded == True:
break
if game.hasEnded == True:
break
table, hand = game.last()
with Context():
table, hand = game.last()
Screen.attr_color(C_WHITE, C_GREEN)
Screen.cls()
Screen.attr_reset()
@ -210,7 +257,11 @@ while not exit:
exit = True
elif action == 'MOVE':
# TODO: transition effect
game.advance(*f.getChoices()) # get them from next
src, dst = f.getChoices()
if src[0] is not None and src[1] is not None and dst is not None:
game.move_and_advance(src, dst) # get them from next
else:
continue
elif action == 'DRAW':
game.draw()
game.next_turn()
@ -227,3 +278,10 @@ while not exit:
game.backtrack()
else:
assert False
if game.hasEnded:
print(f'{Fore.RED}' + "Game has ended, player '" + game.winner + "' has won"+f'{Style.RESET_ALL}')
print('TODO: ordina per bene KQ12, mostra le carte in mano agli altri')
print('LOGGER')
print('magari perche` la mossa e` sbagliata')

View file

@ -12,7 +12,10 @@ import symbols as sym
class Table(Tavolo):
def is_valid(self):
return len(self.singles()) == 0 and len(self.getNonValide()) == 0
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]
def widget_repr(self):
for ts in self.cards:
@ -24,6 +27,17 @@ class Table(Tavolo):
seed = card[0].lower()
yi.append(sym.sym[seed][card[1]])
yield yi
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
class Hand:
@ -57,6 +71,8 @@ class WrongMoveException(Exception):
class State:
def __init__(self, ids):
self.deck = make_deck()
self.winner = None
self.hasEnded = False
self.players = dict()
self.table = Table([])
self.round = None
@ -70,6 +86,7 @@ class State:
hand = self.players[self.cur_player]
nhand = Hand(hand.cards + [self.deck.pop()])
self.players[self.cur_player] = nhand
assert len(self.players[self.cur_player].cards) == len(hand.cards) + 1
self.round = None
def next_turn(self):
@ -82,11 +99,15 @@ class State:
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:
if not table.is_valid() or len(set(original.flatten()) - set(table.flatten())) != 0:
raise WrongMoveException()
else:
self.table, self.players[self.cur_player] = table, hand
self.round = None
if len(hand.cards) == 0:
# won
self.hasEnded = True
self.winner = self.cur_player
def last(self):
return self.round[-1]
@ -100,12 +121,16 @@ class State:
def size(self):
return len(self.round)
def advance(self, src, dst):
def move_and_advance(self, src, dst):
table, hand = self.last()
t, h = gioca(table, hand, src, dst)
self.round.append((t, h))
return t, h
def advance(self, table, hand):
self.round.append((table, hand))
return table, hand
def fromJson(j):
hcards = [Card(seed, value) for seed, value in j['hand']]
tcards = []