9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
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");
}




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