1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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;
}
|