From: "Russ Cox" <rsc@plan9.bell-labs.com>
To: 9fans@cse.psu.edu
Subject: Re: [9fans] 150-solitiare
Date: Mon, 31 Mar 2003 00:36:01 -0500 [thread overview]
Message-ID: <f32014c09ca39f058c26a8ab404230f2@plan9.bell-labs.com> (raw)
In-Reply-To: <Pine.LNX.4.30.0303302334001.14649-100000@athena>
I started a gui in Limbo some years ago.
This might be a good starting point. I don't
remember how far I got. The /usr/rsc/cards
directory is lost, but I had filled it with cards
downloaded off the net and converted to
Inferno format.
implement Solitaire;
include "sys.m"; sys: Sys; print, sprint: import sys;
include "draw.m"; draw: Draw;
include "tk.m"; tk: Tk;
include "wmlib.m"; wmlib: Wmlib;
include "rand.m"; rand: Rand;
include "daytime.m"; daytime: Daytime;
Solitaire: module
{
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
t: ref Tk->Toplevel; # bad name for a global
msglab: string; # label for messages
ace: array of ref Cardstack;
pile: array of ref Cardstack;
deck: ref Cardstack;
dealt: ref Cardstack;
suits: con "chds"; # clubs, hearts, diamonds, spades;
carddir: con "@/usr/rsc/cards";
TABLEHT: con 450;
TABLEWID: con 580;
XPAD: con 5;
YPAD: con 20;
YUPLAP: con 17;
YDNLAP: con 4;
XLAP: con 17;
CARDHT: con 96;
CARDWID: con 71;
init(ctxt: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
draw = load Draw Draw->PATH;
tk = load Tk Tk->PATH;
wmlib = load Wmlib Wmlib->PATH;
rand = load Rand Rand->PATH;
daytime = load Daytime Daytime->PATH;
wmlib->init();
(t1, menubut) := wmlib->titlebar(ctxt.screen, "", "Solitaire", Wmlib->Hide);
t = t1;
tk->cmd(t, "image create bitmap waiting -file cursor.wait");
tk->cmd(t, "pack .Wm_t .c -side top -fill x");
readcards();
cmd := chan of string;
tk->namechan(t, cmd, "cmd");
tk->cmd(t, sprint("canvas .c -height %d -width %d -background green",
TABLEHT, TABLEWID));
tk->cmd(t, "pack .Wm_t .c -side top -fill x");
tk->cmd(t, "bind .c <ButtonPress-1> {send cmd B1down %x %y}");
tk->cmd(t, "bind .c <Button-1-Motion> {send cmd B1move %x %y}");
tk->cmd(t, "update");
deal();
drawboard();
for (;;) {
x0, y0, x, y: int;
alt {
s := <- cmd =>
(n, l) := sys->tokenize(s, " \t");
case hd l {
"Quit" =>
exit;
"Reset" =>
deal();
"Enter" =>
print("enter %s\n", hd tl l);
"Leave" =>
print("leave %s\n", hd tl l);
"B1down" =>
x0 = int hd tl l;
y0 = int hd tl tl l;
# mouseDown(x0, y0);
"B1move" =>
x = int hd tl l;
y = int hd tl tl l;
# mouseMove(x, y);
"B1up" =>
x = int hd tl l;
y = int hd tl tl l;
# mouseUp(x0, y0, x, y);
}
menu := <-menubut =>
if(menu[0] == 'e'){
exit;
}
wmlib->titlectl(t, menu);
}
}
}
deal()
{
ace = array[4] of ref Cardstack;
pile = array[7] of ref Cardstack;
for(i:=0; i<4; i++) {
c : Cardstack;
ace[i] = ref c;
ace[i].init(13, "ace_"+string i);
}
for(i=0; i<7; i++) {
c : Cardstack;
pile[i] = ref c;
pile[i].init(13+7, "pile_"+string i);
}
c : Cardstack;
dealt = ref c;
dealt.init(52, "dealt");
deck = shuffle();
for(i=0; i<7; i++) {
for(j:=i; j<7; j++) {
c := deck.pop();
if(i == j)
c.faceup++;
pile[j].push(c);
}
}
for(i=0; i<5; i++) {
c := deck.pop();
c.faceup++;
dealt.push(c);
}
boardmath();
}
drawboard()
{
# for(i:=0; i<7; i++)
# pile[i].draw();
# for(i=0; i<4; i++)
# ace[i].draw();
# deck.draw();
dealt.drawm(3);
}
boardmath()
{
i, x, y, xlap, yuplap, ydnlap: int;
x = XPAD;
y = YPAD+CARDHT+YPAD;
for(i=0; i<7; i++) {
pile[i].x = x;
pile[i].y = y;
pile[i].xlap = 0;
pile[i].yuplap = YUPLAP;
pile[i].ydnlap = YDNLAP;
x += CARDWID+XPAD;
}
x = pile[7-4].x;
y = YPAD;
for(i=0; i<4; i++) {
ace[i].x = x;
ace[i].y = y;
ace[i].xlap = 0;
ace[i].yuplap = ace[i].ydnlap = 0;
x += CARDWID+XPAD;
}
deck.x = XPAD;
deck.y = YPAD;
deck.xlap = deck.yuplap = deck.ydnlap = 0;
dealt.x = XPAD+CARDWID+XPAD;
dealt.y = YPAD;
dealt.xlap = XLAP;
dealt.yuplap = dealt.ydnlap = 0;
}
shuffle() : ref Cardstack
{
order := array[52] of int;
for(i:=0; i<52; i++)
order[i] = i;
rand->init(daytime->now());
for(i=52; i>0; i--) {
r := rand->rand(i);
(order[i-1], order[r]) = (order[r], order[i-1]);
}
cs : Cardstack;
rcs := ref cs;
rcs.init(52, "deck");
for(i=0; i<52; i++) {
c : Card;
j := order[i];
c.index = j;
c.name = suits[j/13:j/13+1] + string(j%13+1);
c.faceup = 0;
rcs.push(c);
}
return rcs;
}
readcards()
{
tk->cmd(t, "cursor -image waiting; update");
s : string;
for(i := 1; i <= 13; i++) {
for(c := 0; c < len suits; c++) {
f := suits[c:c+1] + string i;
getcard("cbit_"+f, f);
}
}
getcard("cbit_back", "back");
tk->cmd(t, sprint("image create bitmap cbit_none "+
"-file %s/none.bit -maskfile %s/none.mask",
carddir, carddir));
tk->cmd(t, "cursor -default; update");
}
getcard(card, bitmap: string)
{
tk->cmd(t, sprint("image create bitmap %s -file %s/%s.bit -maskfile %s/card.mask",
card, carddir, bitmap, carddir));
}
xcmd(t: ref Tk->Toplevel, s: string)
{
i := tk->cmd(t, s);
sys->print("%s returns %s...\n", s, i);
}
Card: adt
{
index: int;
name: string;
faceup: int;
draw: fn(c: self Card, x, y: int);
};
cardat(x,y: int, name, img: string)
{
tk->cmd(t, sprint(".c delete %s", name));
xcmd(t, sprint(".c create image %d %d -image %s -tags %s",
x+CARDWID/2, y+CARDHT/2, img, name));
xcmd(t, sprint("bind .c.%s <Enter> {send cmd Enter %s}",
name, name));
tk->cmd(t, sprint("bind .c.%s <Leave> {send cmd Leave %s}",
name, name));
}
Card.draw(c: self Card, x, y: int)
{
if(c.faceup)
cardat(x, y, "card_"+c.name, "cbit_"+c.name);
else
cardat(x, y, "card_"+c.name, "cbit_back");
}
Cardstack: adt
{
c: array of Card;
n, sz: int;
xlap, yuplap, ydnlap: int;
x, y: int;
name: string;
pop: fn(cs: self ref Cardstack) : Card;
push: fn(cs: self ref Cardstack, c: Card);
init: fn(cs: self ref Cardstack, sz: int, s: string);
putarray: fn(cs: self ref Cardstack, ca: array of Card);
draw: fn(cs: self ref Cardstack);
drawm: fn(cs: self ref Cardstack, m: int);
};
Cardstack.pop(cs: self ref Cardstack) : Card
{
if(cs.n > 0)
return cs.c[--cs.n];
rv : Card;
rv.index = -1;
return rv;
}
Cardstack.push(cs: self ref Cardstack, c: Card)
{
if(cs.n < cs.sz)
cs.c[cs.n++] = c;
}
Cardstack.init(cs: self ref Cardstack, sz: int, s:string)
{
cs.sz = sz;
cs.c = array[sz] of Card;
cs.n = 0;
cs.name = s;
}
Cardstack.putarray(cs: self ref Cardstack, ca: array of Card)
{
for(i:=0; i<len ca; i++)
cs.push(ca[i]);
}
Cardstack.draw(cs: self ref Cardstack)
{
x := cs.x;
y := cs.y;
cardat(x, y, cs.name, "cbit_none");
for(i:=0; i<cs.n; i++) {
cs.c[i].draw(x, y);
x += cs.xlap;
if(cs.c[i].faceup)
y += cs.yuplap;
else
y += cs.ydnlap;
}
tk->cmd(t, "update");
}
Cardstack.drawm(cs: self ref Cardstack, max: int)
{
x := cs.x;
y := cs.y;
cardat(x, y, cs.name, "cbit_none");
i := cs.n-max;
if(i < 0)
i = 0;
for(;i<cs.n; i++) {
cs.c[i].draw(x, y);
x += cs.xlap;
if(cs.c[i].faceup)
y += cs.yuplap;
else
y += cs.ydnlap;
}
tk->cmd(t, "update");
}
prev parent reply other threads:[~2003-03-31 5:36 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-03-31 4:42 Sam
2003-03-31 5:14 ` andrey mirtchovski
2003-03-31 5:36 ` Russ Cox [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f32014c09ca39f058c26a8ab404230f2@plan9.bell-labs.com \
--to=rsc@plan9.bell-labs.com \
--cc=9fans@cse.psu.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).