# 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(nil: int, user, nil: 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;}
# 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(nil: int, user, nil: 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;
}