implement Tricks;include "sys.m"; sys: Sys;include "draw.m";include "sets.m"; sets: Sets; Set, All, None: import sets;include "../spree.m"; spree: Spree; Attributes, Range, Object, Clique, Member: import spree;include "cardlib.m"; cardlib: Cardlib; Card, getcard: import cardlib;include "tricks.m"; clique: ref Clique; init(mod: Spree, g: ref Clique, cardlibmod: Cardlib){ sys = load Sys Sys->PATH; sets = load Sets Sets->PATH; if (sets == nil) panic(sys->sprint("cannot load %s: %r", Sets->PATH)); clique = g; spree = mod; cardlib = cardlibmod;} defaultrank := array[13] of {12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; # XXX should take a "rank" array so that we can cope with custom# card rankingTrick.new(pile: ref Object, trumps: int, hands: array of ref Object, rank: array of int): ref Trick{ t := ref Trick; t.highcard = t.startcard = Card(-1, -1, -1); t.winner = -1; t.trumps = trumps; t.pile = pile; t.hands = hands; if (rank == nil) rank = defaultrank; t.rank = rank; return t;} Trick.archive(t: self ref Trick, archiveobj: ref Object, name: string){ a := clique.newobject(archiveobj, None, "trick"); cardlib->setarchivename(a, name); a.setattr("trumps", string t.trumps, None); a.setattr("winner", string t.winner, None); a.setattr("startcard.n", string t.startcard.number, None); a.setattr("startcard.suit", string t.startcard.suit, None); a.setattr("highcard.n", string t.highcard.number, None); a.setattr("highcard.suit", string t.highcard.suit, None); cardlib->setarchivename(t.pile, name + ".pile"); cardlib->archivearray(t.hands, name); for (i := 0; i < len t.rank; i++) if (t.rank[i] != defaultrank[i]) break; if (i < len t.rank) { r := ""; for (i = 0; i < len t.rank; i++) r += " " + string t.rank[i]; a.setattr("rank", r, None); }} Trick.unarchive(nil: ref Object, name: string): ref Trick{ t := ref Trick; a := cardlib->getarchiveobj(name); t.trumps = int a.getattr("trumps"); t.winner = int a.getattr("winner"); t.startcard.number = int a.getattr("startcard.n"); t.startcard.suit = int a.getattr("startcard.suit"); t.highcard.number = int a.getattr("highcard.n"); t.highcard.suit = int a.getattr("highcard.suit"); t.pile = cardlib->getarchiveobj(name + ".pile"); t.hands = cardlib->getarchivearray(name); r := a.getattr("rank"); if (r != nil) { (nil, toks) := sys->tokenize(r, " "); t.rank = array[len toks] of int; i := 0; for (; toks != nil; toks = tl toks) t.rank[i++] = int hd toks; } else t.rank = defaultrank; return t;} Trick.play(t: self ref Trick, ord, idx: int): string{ stack := t.hands[ord]; if (idx < 0 || idx >= len stack.children) return "invalid card to play"; c := getcard(stack.children[idx]); c.number = t.rank[c.number]; if (len t.pile.children == 0) { t.winner = ord; t.startcard = t.highcard = c; } else { if (c.suit != t.startcard.suit) { if (containssuit(stack, t.startcard.suit)) return "you must play the suit that was led"; if (c.suit == t.trumps && (t.highcard.suit != t.trumps || c.number > t.highcard.number)) { t.highcard = c; t.winner = ord; } } else if (c.suit == t.highcard.suit && c.number > t.highcard.number) { t.highcard = c; t.winner = ord; } } stack.transfer((idx, idx + 1), t.pile, len t.pile.children); stack.setattr("n", string (int stack.getattr("n") - 1), All); return nil;} containssuit(stack: ref Object, suit: int): int{ ch := stack.children; n := len ch; for (i := 0; i < n; i++) if (getcard(ch[i]).suit == suit) return 1; return 0;} panic(e: string){ sys->fprint(sys->fildes(2), "tricks panic: %s\n", e); raise "panic";}
implement Tricks;
include "sys.m";
sys: Sys;
include "draw.m";
include "sets.m";
sets: Sets;
Set, All, None: import sets;
include "../spree.m";
spree: Spree;
Attributes, Range, Object, Clique, Member: import spree;
include "cardlib.m";
cardlib: Cardlib;
Card, getcard: import cardlib;
include "tricks.m";
clique: ref Clique;
init(mod: Spree, g: ref Clique, cardlibmod: Cardlib)
{
sys = load Sys Sys->PATH;
sets = load Sets Sets->PATH;
if (sets == nil)
panic(sys->sprint("cannot load %s: %r", Sets->PATH));
clique = g;
spree = mod;
cardlib = cardlibmod;
}
defaultrank := array[13] of {12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
# XXX should take a "rank" array so that we can cope with custom
# card ranking
Trick.new(pile: ref Object, trumps: int, hands: array of ref Object, rank: array of int): ref Trick
{
t := ref Trick;
t.highcard = t.startcard = Card(-1, -1, -1);
t.winner = -1;
t.trumps = trumps;
t.pile = pile;
t.hands = hands;
if (rank == nil)
rank = defaultrank;
t.rank = rank;
return t;
}
Trick.archive(t: self ref Trick, archiveobj: ref Object, name: string)
{
a := clique.newobject(archiveobj, None, "trick");
cardlib->setarchivename(a, name);
a.setattr("trumps", string t.trumps, None);
a.setattr("winner", string t.winner, None);
a.setattr("startcard.n", string t.startcard.number, None);
a.setattr("startcard.suit", string t.startcard.suit, None);
a.setattr("highcard.n", string t.highcard.number, None);
a.setattr("highcard.suit", string t.highcard.suit, None);
cardlib->setarchivename(t.pile, name + ".pile");
cardlib->archivearray(t.hands, name);
for (i := 0; i < len t.rank; i++)
if (t.rank[i] != defaultrank[i])
break;
if (i < len t.rank) {
r := "";
for (i = 0; i < len t.rank; i++)
r += " " + string t.rank[i];
a.setattr("rank", r, None);
}
}
Trick.unarchive(nil: ref Object, name: string): ref Trick
{
t := ref Trick;
a := cardlib->getarchiveobj(name);
t.trumps = int a.getattr("trumps");
t.winner = int a.getattr("winner");
t.startcard.number = int a.getattr("startcard.n");
t.startcard.suit = int a.getattr("startcard.suit");
t.highcard.number = int a.getattr("highcard.n");
t.highcard.suit = int a.getattr("highcard.suit");
t.pile = cardlib->getarchiveobj(name + ".pile");
t.hands = cardlib->getarchivearray(name);
r := a.getattr("rank");
if (r != nil) {
(nil, toks) := sys->tokenize(r, " ");
t.rank = array[len toks] of int;
i := 0;
for (; toks != nil; toks = tl toks)
t.rank[i++] = int hd toks;
} else
t.rank = defaultrank;
return t;
}
Trick.play(t: self ref Trick, ord, idx: int): string
{
stack := t.hands[ord];
if (idx < 0 || idx >= len stack.children)
return "invalid card to play";
c := getcard(stack.children[idx]);
c.number = t.rank[c.number];
if (len t.pile.children == 0) {
t.winner = ord;
t.startcard = t.highcard = c;
} else {
if (c.suit != t.startcard.suit) {
if (containssuit(stack, t.startcard.suit))
return "you must play the suit that was led";
if (c.suit == t.trumps &&
(t.highcard.suit != t.trumps ||
c.number > t.highcard.number)) {
t.highcard = c;
t.winner = ord;
}
} else if (c.suit == t.highcard.suit && c.number > t.highcard.number) {
t.highcard = c;
t.winner = ord;
}
}
stack.transfer((idx, idx + 1), t.pile, len t.pile.children);
stack.setattr("n", string (int stack.getattr("n") - 1), All);
return nil;
}
containssuit(stack: ref Object, suit: int): int
{
ch := stack.children;
n := len ch;
for (i := 0; i < n; i++)
if (getcard(ch[i]).suit == suit)
return 1;
return 0;
}
panic(e: string)
{
sys->fprint(sys->fildes(2), "tricks panic: %s\n", e);
raise "panic";
}