summaryrefslogtreecommitdiff
path: root/appl/lib/scoretable.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/scoretable.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/lib/scoretable.b')
-rw-r--r--appl/lib/scoretable.b150
1 files changed, 150 insertions, 0 deletions
diff --git a/appl/lib/scoretable.b b/appl/lib/scoretable.b
new file mode 100644
index 00000000..a466763b
--- /dev/null
+++ b/appl/lib/scoretable.b
@@ -0,0 +1,150 @@
+# Copyright © 1999 Roger Peppe. All rights reserved.
+implement Scoretable;
+include "sys.m";
+ sys: Sys;
+ stderr: ref Sys->FD;
+include "draw.m";
+include "bufio.m";
+ bufio: Bufio;
+ Iobuf: import bufio;
+include "scoretable.m";
+
+# this is the cut-down version - it doesn't bother
+# with score table locking at all; there is such a version,
+# but it needs a lock server, so is often more hassle than
+# it's worth. if you want a distributed score file, contact
+# rog@vitanuova.com
+# currently this module is only used by tetris - the interface
+# will probably change in the future.
+
+scorefile: string;
+username: string;
+
+MAXSCORES: con 10;
+
+init(port: int, user, name: string, sfile: string): (int, string)
+{
+ if (sys == nil) {
+ sys = load Sys Sys->PATH;
+ stderr = sys->fildes(2);
+ bufio = load Bufio Bufio->PATH;
+ if (bufio == nil) {
+ sys = nil;
+ return (-1, sys->sprint("cannot load %s: %r", Bufio->PATH));
+ }
+ }
+ username = user;
+ lock();
+ scorefd: ref Sys->FD;
+ if ((scorefd = sys->open(sfile, Sys->ORDWR)) == nil
+ && (scorefd = sys->create(sfile, Sys->ORDWR, 8r666)) == nil) {
+ unlock();
+ return (-1, sys->sprint("cannot open %s: %r", sfile));
+ }
+ unlock();
+ scorefile = sfile;
+ return (0, nil);
+}
+
+lock()
+{
+}
+
+unlock()
+{
+}
+
+scores(): list of Score
+{
+ lock();
+ sl := readscores();
+ unlock();
+ return sl;
+}
+
+readscores(): list of Score
+{
+ sl: list of Score;
+ iob := bufio->open(scorefile, Sys->OREAD);
+ if (iob == nil)
+ return nil;
+ iob.seek(big 0, Bufio->SEEKSTART);
+ while ((s := iob.gets('\n')) != nil) {
+ (n, toks) := sys->tokenize(s, " \t\n");
+ if (toks == nil)
+ continue;
+ if (n < 2) {
+ sys->fprint(stderr, "bad line in score table: %s", s);
+ continue;
+ }
+ score: Score;
+ (score.user, toks) = (hd toks, tl toks);
+ (score.score, toks) = (int hd toks, tl toks);
+ score.other = nil;
+ while (toks != nil) {
+ score.other += hd toks;
+ if (tl toks != nil)
+ score.other += " ";
+ toks = tl toks;
+ }
+ sl = score :: sl;
+ }
+ iob.close();
+ nl: list of Score;
+ while (sl != nil) {
+ nl = hd sl :: nl;
+ sl = tl sl;
+ }
+ return nl;
+}
+
+writescores(sl: list of Score)
+{
+ scoreiob := bufio->open(scorefile, Sys->OWRITE|Sys->OTRUNC);
+ if (scoreiob == nil) {
+ sys->fprint(stderr, "scoretable: cannot write score file '%s': %r\n", scorefile);
+ return;
+ }
+ scoreiob.seek(big 0, Bufio->SEEKSTART);
+ n := 0;
+ while (sl != nil && n < MAXSCORES) {
+ s := hd sl;
+ scoreiob.puts(sys->sprint("%s %d %s\n", s.user, s.score, s.other));
+ n++;
+ sl = tl sl;
+ }
+ scoreiob.close();
+}
+
+setscore(score: int, other: string): int
+{
+ lock();
+ sl := readscores();
+ nl: list of Score;
+ done := 0;
+ n := rank := 0;
+ while (sl != nil) {
+ s := hd sl;
+ if (score > s.score && !done) {
+ nl = Score(username, score, other) :: nl;
+ rank = n;
+ done = 1;
+ }
+ nl = s :: nl;
+ sl = tl sl;
+ n++;
+ }
+ if (!done) {
+ nl = Score(username, score, other) :: nl;
+ rank = n;
+ }
+ sl = nil;
+ while (nl != nil) {
+ sl = hd nl :: sl;
+ nl = tl nl;
+ }
+ writescores(sl);
+ unlock();
+ # XXX minor race condition in returning the rank, not our idea of the rank.
+ return rank;
+}