merge
This commit is contained in:
commit
22ec6165bc
19 changed files with 2258 additions and 24 deletions
|
@ -1,6 +1,10 @@
|
|||
syntax: regexp
|
||||
^sys/src/.*\.[ao]?[12578vqki]?$
|
||||
^sys/src/(.*/)?[12578vqki]\..*$
|
||||
^sys/lib/python/.*\.(pyo|pyc|exe)$
|
||||
^(dev|fd|net|srv|env|root|boot|mnt|n|bin|tmp)/
|
||||
^(386|68000|68020|alpha|amd64|arm|power|power64|sparc|sparc64)/(bin|lib)/
|
||||
^386/(9(pc|boot).*|pbs|mbr|init)
|
||||
^acme/bin/(386|68000|68020|alpha|amd64|arm|power|power64|sparc|sparc64)/
|
||||
^usr/
|
||||
^sys/lib/pkg
|
|
@ -6,10 +6,9 @@
|
|||
# ip/ipconfig -g your-gateway ether /net/ether0 your-ip-address your-subnet-mask
|
||||
|
||||
# example: adjust to fit your network
|
||||
ip/ipconfig -g 192.168.0.1 ether /net/ether0 192.168.0.2 255.255.255.0
|
||||
ndb/dns -rs
|
||||
#ip/ipconfig -g 192.168.0.1 ether /net/ether0 192.168.0.2 255.255.255.0
|
||||
#ndb/dns -rs
|
||||
#aux/timesync -Ln pool.ntp.org
|
||||
|
||||
# outgoing mail will appear to originate from this domain
|
||||
site=9front
|
||||
|
||||
ntp=pool.ntp.org
|
||||
#site=9front
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
#!/bin/rc
|
||||
# cpu-specific startup
|
||||
|
||||
# Since booting from venti could have started loopback,
|
||||
# don't test for existing interfaces, just use ipconfig.
|
||||
# ip/ipconfig -g your-gateway ether /net/ether0 your-ip-address your-subnet-mask
|
||||
|
||||
# example: adjust to fit your network
|
||||
ip/ipconfig -g 192.168.0.1 ether /net/ether0 192.168.0.2 255.255.255.0
|
||||
ndb/dns -r
|
||||
#ip/ipconfig -g 192.168.0.1 ether /net/ether0 192.168.0.2 255.255.255.0
|
||||
#ndb/dns -r
|
||||
#aux/timesync -Ln pool.ntp.org
|
||||
|
||||
# outgoing mail will appear to originate from this domain
|
||||
site=9front
|
||||
|
||||
ntp=pool.ntp.org
|
||||
#site=9front
|
||||
|
|
1487
lib/manifesto
Normal file
1487
lib/manifesto
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9,3 +9,5 @@
|
|||
# hostid=bootes
|
||||
# uid=!sys uid=!adm uid=*
|
||||
#
|
||||
hostid=bootes
|
||||
uid=!sys uid=!adm uid=*
|
||||
|
|
|
@ -8,9 +8,9 @@ database=
|
|||
|
||||
auth=sources.cs.bell-labs.com authdom=outside.plan9.bell-labs.com
|
||||
|
||||
auth=cirno.9front authdom=9front
|
||||
#auth=cirno.9front authdom=9front
|
||||
|
||||
ntp=pool.ntp.org
|
||||
#ntp=pool.ntp.org
|
||||
|
||||
#
|
||||
# because the public demands the name localsource
|
||||
|
@ -18,12 +18,12 @@ ntp=pool.ntp.org
|
|||
ip=127.0.0.1 sys=localhost dom=localhost
|
||||
|
||||
# example: adjust to fit your network
|
||||
ipnet=9front ip=192.168.0.0 ipmask=255.255.255.0
|
||||
auth=cirno.9front
|
||||
cpu=cirno.9front
|
||||
dns=192.168.0.2
|
||||
dnsdom=9front
|
||||
smtp=cirno.9front
|
||||
|
||||
ip=192.168.0.1 sys=gw dom=gw.9front
|
||||
ip=192.168.0.2 sys=cirno dom=cirno.9front
|
||||
#ipnet=9front ip=192.168.0.0 ipmask=255.255.255.0
|
||||
# auth=cirno.9front
|
||||
# cpu=cirno.9front
|
||||
# dns=192.168.0.2
|
||||
# dnsdom=9front
|
||||
# smtp=cirno.9front
|
||||
#
|
||||
#ip=192.168.0.1 sys=gw dom=gw.9front
|
||||
#ip=192.168.0.2 sys=cirno dom=cirno.9front
|
||||
|
|
6
rc/bin/hold
Executable file
6
rc/bin/hold
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/rc
|
||||
{
|
||||
echo holdon >[1=3]
|
||||
cat $1 > /dev/cons
|
||||
cat /dev/cons > $1
|
||||
} >[3]/dev/consctl
|
|
@ -2037,6 +2037,7 @@ atapnp(void)
|
|||
case (0x24CB<<16)|0x8086: /* 82801DB (ICH4, High-End) */
|
||||
case (0x24DB<<16)|0x8086: /* 82801EB (ICH5) */
|
||||
case (0x25A3<<16)|0x8086: /* 6300ESB (E7210) */
|
||||
case (0x2653<<16)|0x8086: /* 82801FBM SATA */
|
||||
case (0x266F<<16)|0x8086: /* 82801FB (ICH6) */
|
||||
case (0x27DF<<16)|0x8086: /* 82801G SATA (ICH7) */
|
||||
case (0x27C0<<16)|0x8086: /* 82801GB SATA AHCI (ICH7) */
|
||||
|
|
|
@ -740,11 +740,22 @@ cmd_files(int, char *[])
|
|||
print("%ld out of %ld files used\n", n, conf.nfile);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_chatty(int argc, char *argv[])
|
||||
{
|
||||
if(argc < 2) {
|
||||
print("cmd_chatty: usage: chatty n\n");
|
||||
return;
|
||||
}
|
||||
chatty = atoi(argv[1]);
|
||||
}
|
||||
|
||||
static void
|
||||
installcmds(void)
|
||||
{
|
||||
cmd_install("allow", "-- disable permission checking", cmd_allow);
|
||||
cmd_install("cfs", "[file] -- set current filesystem", cmd_cfs);
|
||||
cmd_install("chatty", "n -- set chattiness", cmd_chatty);
|
||||
cmd_install("clean", "file [bno [addr]] -- block print/fix", cmd_clean);
|
||||
cmd_install("check", "[options]", cmd_check);
|
||||
cmd_install("clri", "[file ...] -- purge files/dirs", cmd_clri);
|
||||
|
|
21
sys/src/cmd/pkg/create
Executable file
21
sys/src/cmd/pkg/create
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/bin/rc -e
|
||||
|
||||
i=`{basename $1}
|
||||
d=$1
|
||||
echo Creating $i
|
||||
C=`{pwd}
|
||||
@{
|
||||
rfork en
|
||||
cd $d
|
||||
mkdir /tmp/$i
|
||||
mk
|
||||
divergefs -p /tmp/$i /
|
||||
mk install clean
|
||||
unmount /
|
||||
}
|
||||
cd /tmp/$i/files
|
||||
rm -r env
|
||||
tar cv * | bzip2 -9 > $C/$i.tbz
|
||||
cd /tmp
|
||||
rm -r $i
|
||||
echo Created $C/$i.tbz
|
12
sys/src/cmd/pkg/install
Executable file
12
sys/src/cmd/pkg/install
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/rc -e
|
||||
|
||||
cd /
|
||||
mkdir -p /sys/lib/pkg
|
||||
if (test -s /sys/lib/pkg/$1) {
|
||||
echo $i already installed
|
||||
exit
|
||||
}
|
||||
echo Installing $1
|
||||
hget http://pkg.violetti.org/$cputype/$1.tbz | bunzip2 | pkg/unpkg>[2]/sys/lib/pkg/$1
|
||||
echo Done
|
||||
|
3
sys/src/cmd/pkg/list
Executable file
3
sys/src/cmd/pkg/list
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/rc
|
||||
|
||||
hget http://pkg.violetti.org/$cputype | htmlfmt | grep '\.tbz' | sed -e 's/\.tbz$//'
|
20
sys/src/cmd/pkg/mkfile
Normal file
20
sys/src/cmd/pkg/mkfile
Normal file
|
@ -0,0 +1,20 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
all: $O.unpkg
|
||||
echo
|
||||
|
||||
$O.unpkg: unpkg.c
|
||||
$CC unpkg.c
|
||||
$LD -o $O.unpkg unpkg.$O
|
||||
|
||||
install:V: $O.unpkg
|
||||
mkdir -p /$objtype/bin/pkg
|
||||
cp $O.unpkg /$objtype/bin/pkg/unpkg
|
||||
cp create install list remove /$objtype/bin/pkg
|
||||
|
||||
clean:
|
||||
rm -f $O.unpkg *.$O
|
||||
|
||||
nuke: clean
|
||||
rm -f /$objtype/bin/pkg/*
|
||||
|
18
sys/src/cmd/pkg/remove
Executable file
18
sys/src/cmd/pkg/remove
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/rc -e
|
||||
|
||||
cd /
|
||||
if(test -s /sys/lib/pkg/$1) {
|
||||
fs=(`{cat /sys/lib/pkg/$1 | awk '{print $1}'})
|
||||
ss=(`{cat /sys/lib/pkg/$1 | awk '{print $2}'})
|
||||
for(i in `{seq $#fs}) {
|
||||
s=`{sha1sum $fs($i) | awk '{print $1}' | tr a-z A-Z}
|
||||
if(test $s '=' $ss($i)) {
|
||||
echo D $fs($i)
|
||||
rm $fs($i)
|
||||
}
|
||||
if not {
|
||||
echo M $fs($i) NOT DELETING
|
||||
}
|
||||
}
|
||||
rm /sys/lib/pkg/$1
|
||||
}
|
100
sys/src/cmd/pkg/unpkg.c
Normal file
100
sys/src/cmd/pkg/unpkg.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <mp.h>
|
||||
#include <libsec.h>
|
||||
|
||||
struct th {
|
||||
char *name;
|
||||
ulong perm;
|
||||
ulong size;
|
||||
char type;
|
||||
char *user, *group;
|
||||
};
|
||||
|
||||
static char *sndup(char* s, ulong n) {
|
||||
char *d, *p;
|
||||
p = memchr(s, 0, n);
|
||||
if(p)
|
||||
n = p-s;
|
||||
d = malloc(n+1);
|
||||
memcpy(d,s,n);
|
||||
d[n] = 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
int readheader(int fd, struct th* th) {
|
||||
int i;
|
||||
char b[512];
|
||||
if(readn(fd, b, 512) != 512) return -1;
|
||||
|
||||
// Check for end of archive
|
||||
for(i=0; i<512; i++) {
|
||||
if(b[i]!=0) goto rhok;
|
||||
}
|
||||
if(readn(fd, b, 512) != 512) return -1;
|
||||
for(i=0; i<512; i++) {
|
||||
if(b[i]!=0) return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
rhok:
|
||||
th->name = sndup(b, 100);
|
||||
th->perm = strtoul(b+100, nil, 8);
|
||||
th->size = strtoul(b+124, nil, 8);
|
||||
th->type = b[156];
|
||||
th->user = sndup(b+265, 32);
|
||||
th->group= sndup(b+297, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
while(1) {
|
||||
struct th th;
|
||||
ulong off;
|
||||
uchar b[512];
|
||||
DigestState *s;
|
||||
int wfd;
|
||||
int r = readheader(0, &th);
|
||||
if(r <= 0) return r;
|
||||
|
||||
switch(th.type) {
|
||||
case '5':
|
||||
create(th.name, OREAD, DMDIR|th.perm);
|
||||
break;
|
||||
case '0': case 0:
|
||||
print("A %s\n", th.name);
|
||||
r = access(th.name, 0);
|
||||
if(r == 0) {
|
||||
print("File already exists: %s\n", th.name);
|
||||
return -1;
|
||||
}
|
||||
if((wfd = create(th.name, OWRITE, th.perm)) < 0) {
|
||||
print("Create failed: %s\n", th.name);
|
||||
return -1;
|
||||
}
|
||||
s = nil;
|
||||
for(off=0; off<th.size; off+=512) {
|
||||
int n = th.size-off;
|
||||
n = n<512 ? n : 512;
|
||||
if(readn(0, b, 512) != 512) return -1;
|
||||
if(write(wfd, b, n) != n) return -1;
|
||||
s = sha1(b, n, nil, s);
|
||||
}
|
||||
|
||||
uchar digest[20], hdigest[41];
|
||||
sha1(nil, 0, digest, s);
|
||||
enc16((char*)hdigest, 41, digest, 20);
|
||||
fprint(2, "%s\t%s\n", th.name, hdigest);
|
||||
close(wfd);
|
||||
break;
|
||||
default:
|
||||
print("Unknown file type '%c'\n", th.type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(th.name);
|
||||
free(th.user);
|
||||
free(th.group);
|
||||
}
|
||||
}
|
|
@ -157,9 +157,11 @@ main(int argc, char *argv[])
|
|||
int p[2];
|
||||
int fd;
|
||||
int stdio = 0;
|
||||
int mountflags;
|
||||
|
||||
service = "ramfs";
|
||||
defmnt = "/tmp";
|
||||
mountflags = 0;
|
||||
ARGBEGIN{
|
||||
case 'i':
|
||||
defmnt = 0;
|
||||
|
@ -186,9 +188,20 @@ main(int argc, char *argv[])
|
|||
defmnt = 0;
|
||||
service = EARGF(usage());
|
||||
break;
|
||||
case 'b':
|
||||
mountflags |= MBEFORE;
|
||||
break;
|
||||
case 'c':
|
||||
mountflags |= MCREATE;
|
||||
break;
|
||||
case 'a':
|
||||
mountflags |= MAFTER;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
if(mountflags == 0)
|
||||
mountflags = MREPL | MCREATE;
|
||||
|
||||
if(pipe(p) < 0)
|
||||
error("pipe failed");
|
||||
|
@ -239,7 +252,7 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
default:
|
||||
close(p[0]); /* don't deadlock if child fails */
|
||||
if(defmnt && mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0)
|
||||
if(defmnt && mount(p[1], -1, defmnt, mountflags, "") < 0)
|
||||
error("mount failed");
|
||||
}
|
||||
exits(0);
|
||||
|
@ -902,6 +915,6 @@ estrdup(char *q)
|
|||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: %s [-Dipsu] [-m mountpoint] [-S srvname]\n", argv0);
|
||||
fprint(2, "usage: %s [-Dipsubac] [-m mountpoint] [-S srvname]\n", argv0);
|
||||
exits("usage");
|
||||
}
|
||||
|
|
530
sys/src/games/glendy.c
Normal file
530
sys/src/games/glendy.c
Normal file
|
@ -0,0 +1,530 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <event.h>
|
||||
|
||||
enum{
|
||||
/* difficulty levels (how many circles are initially occupied) */
|
||||
DEasy, /* 10≤x<15 */
|
||||
DMed, /* 5≤x<10 */
|
||||
DHard, /* 0≤x<5 */
|
||||
|
||||
/* dynamic? original game has a fixed grid size, but we don't need to abide by it */
|
||||
SzX = 11,
|
||||
SzY = 11,
|
||||
|
||||
Border = 10,
|
||||
/* movement directions */
|
||||
NE,
|
||||
E,
|
||||
SE,
|
||||
SW,
|
||||
W,
|
||||
NW,
|
||||
|
||||
Won = 1, /* game-ending states */
|
||||
Lost = 2,
|
||||
};
|
||||
|
||||
Font *font;
|
||||
|
||||
int difficulty = DMed;
|
||||
int finished;
|
||||
|
||||
int grid[SzX][SzY];
|
||||
int ogrid[SzX][SzY]; /* so we can restart levels */
|
||||
|
||||
Image *gl; /* glenda */
|
||||
Image *glm; /* glenda's mask */
|
||||
Image *cc; /* clicked */
|
||||
Image *ec; /* empty; not clicked */
|
||||
Image *bg;
|
||||
Image *lost;
|
||||
Image *won;
|
||||
|
||||
|
||||
char *mbuttons[] =
|
||||
{
|
||||
"easy",
|
||||
"medium",
|
||||
"hard",
|
||||
0
|
||||
};
|
||||
|
||||
char *rbuttons[] =
|
||||
{
|
||||
"new",
|
||||
"reset",
|
||||
"exit",
|
||||
0
|
||||
};
|
||||
|
||||
Menu mmenu =
|
||||
{
|
||||
mbuttons,
|
||||
};
|
||||
|
||||
Menu rmenu =
|
||||
{
|
||||
rbuttons,
|
||||
};
|
||||
|
||||
Image *
|
||||
eallocimage(Rectangle r, int repl, uint color)
|
||||
{
|
||||
Image *tmp;
|
||||
|
||||
tmp = allocimage(display, r, screen->chan, repl, color);
|
||||
if(tmp == nil)
|
||||
sysfatal("cannot allocate buffer image: %r");
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Image *
|
||||
eloadfile(char *path)
|
||||
{
|
||||
Image *img;
|
||||
int fd;
|
||||
|
||||
fd = open(path, OREAD);
|
||||
if(fd < 0) {
|
||||
fprint(2, "cannot open image file %s: %r\n", path);
|
||||
exits("image");
|
||||
}
|
||||
img = readimage(display, fd, 0);
|
||||
if(img == nil)
|
||||
sysfatal("cannot load image: %r");
|
||||
close(fd);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
allocimages(void)
|
||||
{
|
||||
Rectangle one = Rect(0, 0, 1, 1);
|
||||
|
||||
cc = eallocimage(one, 1, 0x777777FF);
|
||||
ec = eallocimage(one, 1, DPalegreen);
|
||||
bg = eallocimage(one, 1, DPurpleblue);
|
||||
lost = eallocimage(one, 1, DRed);
|
||||
won = eallocimage(one, 1, DGreen);
|
||||
gl = eloadfile("/lib/face/48x48x4/g/glenda.1");
|
||||
|
||||
glm = allocimage(display, Rect(0, 0, 48, 48), gl->chan, 1, DCyan);
|
||||
if(glm == nil)
|
||||
sysfatal("cannot allocate mask: %r");
|
||||
|
||||
draw(glm, glm->r, display->white, nil, ZP);
|
||||
gendraw(glm, glm->r, display->black, ZP, gl, gl->r.min);
|
||||
freeimage(gl);
|
||||
gl = display->black;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* unnecessary calculations here, but it's fine */
|
||||
Point
|
||||
board2pix(int x, int y)
|
||||
{
|
||||
float d, rx, ry, yh;
|
||||
int nx, ny;
|
||||
|
||||
d = (float)(Dx(screen->r) > Dy(screen->r)) ? Dy(screen->r) -20 : Dx(screen->r) -20;
|
||||
rx = d/(float)SzX;
|
||||
rx = rx/2.0;
|
||||
ry = d/(float)SzY;
|
||||
ry = ry/2.0;
|
||||
|
||||
yh = ry/3.73205082;
|
||||
|
||||
nx = (int)((float)x*rx*2.0+rx +(y%2?rx:0.0)); /* nx = x*(2rx) + rx + rx (conditional) */
|
||||
ny = (int)((float)y*(ry*2.0-(y>0?yh:0.0)) + ry); /* ny = y*(2ry-yh) +ry */
|
||||
return Pt(nx, ny);
|
||||
}
|
||||
|
||||
Point
|
||||
pix2board(int x, int y)
|
||||
{
|
||||
float d, rx, ry, yh;
|
||||
int ny, nx;
|
||||
|
||||
/* XXX: float→int causes small rounding errors */
|
||||
|
||||
d = (float)(Dx(screen->r) > Dy(screen->r)) ? Dy(screen->r) -20: Dx(screen->r)-20;
|
||||
rx = d/(float)SzX;
|
||||
rx = rx/2.0;
|
||||
ry =d/(float)SzY;
|
||||
ry = ry/2.0;
|
||||
|
||||
yh = ry/3.73205082;
|
||||
|
||||
/* reverse board2pix() */
|
||||
ny = (int)(((float)y - ry)/(2*ry - ((y>2*ry)?yh:0.0)) + 0.5); /* ny = (y - ry)/(2ry-yh) */
|
||||
nx = (int)(((float)x - rx - (ny%2?rx:0.0))/(rx*2.0) + 0.5); /* nx = (x - rx - rx)/2rx */
|
||||
|
||||
if (nx >= SzX)
|
||||
nx = SzX-1;
|
||||
if (ny >=SzY)
|
||||
ny = SzY-1;
|
||||
|
||||
return Pt(nx, ny);
|
||||
}
|
||||
|
||||
void
|
||||
initlevel(void)
|
||||
{
|
||||
int i, cnt = 10, x, y;
|
||||
|
||||
for(x = 0; x < SzX; x++)
|
||||
for(y = 0; y < SzY; y++)
|
||||
ogrid[x][y] = 100;
|
||||
|
||||
switch(difficulty){
|
||||
case DEasy:
|
||||
cnt = 10 + nrand(5);
|
||||
break;
|
||||
case DMed:
|
||||
cnt = 5 + nrand(5);
|
||||
break;
|
||||
case DHard:
|
||||
cnt = nrand(5);
|
||||
break;
|
||||
}
|
||||
for(i = 0; i < cnt; i++) {
|
||||
do {
|
||||
x = nrand(SzX);
|
||||
y = nrand(SzY);
|
||||
} while(ogrid[x][y] != 100);
|
||||
ogrid[x][y] = 999;
|
||||
}
|
||||
|
||||
ogrid[SzX/2][SzY/2] = 1000;
|
||||
|
||||
memcpy(grid, ogrid, sizeof grid);
|
||||
|
||||
finished = 0;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
drawlevel(void)
|
||||
{
|
||||
Point p;
|
||||
int x, y, rx, ry, d;
|
||||
char *s = nil;
|
||||
|
||||
if(finished)
|
||||
draw(screen, screen->r, finished==Won?won:lost, nil, ZP);
|
||||
else
|
||||
draw(screen, screen->r, bg, nil, ZP);
|
||||
|
||||
d = (Dx(screen->r) > Dy(screen->r)) ? Dy(screen->r) -20: Dx(screen->r) -20;
|
||||
rx = (int)ceil((float)(d-2*Border)/(float)SzX)/2;
|
||||
ry = (int)ceil((float)(d-2*Border)/(float)SzY)/2;
|
||||
|
||||
for(x = 0; x < SzX; x++) {
|
||||
for(y = 0; y < SzY; y++) {
|
||||
p = board2pix(x, y);
|
||||
switch(grid[x][y]){
|
||||
case 999:
|
||||
fillellipse(screen, addpt(screen->r.min, p), rx, ry, cc, ZP);
|
||||
break;
|
||||
case 1000:
|
||||
p = addpt(screen->r.min, p);
|
||||
fillellipse(screen, p, rx, ry, ec, ZP);
|
||||
p = subpt(p, Pt(24, 24));
|
||||
draw(screen, Rpt(p, addpt(p, Pt(48, 48))), gl, glm, ZP);
|
||||
break;
|
||||
default:
|
||||
fillellipse(screen, addpt(screen->r.min, p), rx, ry, ec, ZP);
|
||||
USED(s);
|
||||
/* uncomment the following to see game state and field scores */
|
||||
/*s = smprint("%d", grid[x][y]);
|
||||
string(screen, addpt(screen->r.min, p), display->black, ZP, font, s);
|
||||
free(s);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
flushimage(display, 1);
|
||||
}
|
||||
|
||||
void
|
||||
domove(int dir, int x, int y)
|
||||
{
|
||||
if(x == 0 || x == SzX-1 || y == 0 || y == SzY-1)
|
||||
goto done;
|
||||
|
||||
switch(dir){
|
||||
case NE:
|
||||
if(y%2)
|
||||
grid[x+1][y-1] = 1000;
|
||||
else
|
||||
grid[x][y-1] = 1000;
|
||||
break;
|
||||
case E:
|
||||
grid[x+1][y] = 1000;
|
||||
break;
|
||||
case SE:
|
||||
if(y%2)
|
||||
grid[x+1][y+1] = 1000;
|
||||
else
|
||||
grid[x][y+1] = 1000;
|
||||
break;
|
||||
case SW:
|
||||
if(y%2)
|
||||
grid[x][y+1] = 1000;
|
||||
else
|
||||
grid[x-1][y+1] = 1000;
|
||||
break;
|
||||
case W:
|
||||
grid[x-1][y] = 1000;
|
||||
break;
|
||||
case NW:
|
||||
if(y%2)
|
||||
grid[x][y-1] = 1000;
|
||||
else
|
||||
grid[x-1][y-1] = 1000;
|
||||
break;
|
||||
}
|
||||
done:
|
||||
grid[x][y] = 100;
|
||||
}
|
||||
|
||||
Point
|
||||
findglenda(void)
|
||||
{
|
||||
int x, y;
|
||||
for(x = 0; x < SzX; x++)
|
||||
for(y = 0; y < SzY; y++)
|
||||
if(grid[x][y] == 1000)
|
||||
return Pt(x, y);
|
||||
return Pt(-1, -1);
|
||||
}
|
||||
|
||||
int
|
||||
checknext(int dir, int x, int y)
|
||||
{
|
||||
switch(dir){
|
||||
case NE:
|
||||
return grid[x+(y%2?1:0)][y-1];
|
||||
case E:
|
||||
return grid[x+1][y];
|
||||
case SE:
|
||||
return grid[x+(y%2?1:0)][y+1];
|
||||
case SW:
|
||||
return grid[x+(y%2?0:-1)][y+1];
|
||||
case W:
|
||||
return grid[x-1][y];
|
||||
case NW:
|
||||
return grid[x+(y%2?0:-1)][y-1];
|
||||
default:
|
||||
sysfatal("andrey messed up big time");
|
||||
}
|
||||
return 1000;
|
||||
}
|
||||
/* the following two routines constitute the "game AI"
|
||||
* they score the field based on the number of moves
|
||||
* required to reach the edge from a particular point
|
||||
* scores > 100 are "dead spots" (this assumes the field
|
||||
* is not larger than ~100*2
|
||||
*
|
||||
* routines need to run at least twice to ensure a field is properly
|
||||
* scored: there are errors that creep up due to the nature of
|
||||
* traversing the board
|
||||
*/
|
||||
int
|
||||
score1(int x, int y) {
|
||||
int dir, min = 999, next;
|
||||
|
||||
if(x == 0 || x == SzX-1 || y == 0 || y == SzY-1)
|
||||
return 1; /* we can always escape from the edges */
|
||||
|
||||
for(dir = NE; dir <= NW; dir++) {
|
||||
next = checknext(dir, x, y);
|
||||
if(next < min)
|
||||
min = next;
|
||||
}
|
||||
return 1+min;
|
||||
}
|
||||
|
||||
void
|
||||
calc(void)
|
||||
{
|
||||
int i, x, y;
|
||||
for(i = 0; i < SzX; i++) /* assumes SzX = SzY */
|
||||
for(x = i; x < SzX-i; x++)
|
||||
for(y = i; y < SzY-i; y++)
|
||||
if(grid[x][y] != 999)
|
||||
grid[x][y] = score1(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
nextglenda(void)
|
||||
{
|
||||
int min =1000, next, dir, nextdir = 0, count = 0;
|
||||
Point p = findglenda();
|
||||
|
||||
calc();
|
||||
calc();
|
||||
calc();
|
||||
|
||||
grid[p.x][p.y] = 1000;
|
||||
|
||||
for(dir = NE; dir <= NW; dir++) {
|
||||
next = checknext(dir, p.x, p.y);
|
||||
if(next < min) {
|
||||
min = next;
|
||||
nextdir = dir;
|
||||
++count;
|
||||
} else if(next == min) {
|
||||
nextdir = (nrand(++count) == 0)?dir:nextdir;
|
||||
}
|
||||
}
|
||||
if(min < 100)
|
||||
domove(nextdir, p.x, p.y);
|
||||
else
|
||||
finished = Won;
|
||||
|
||||
if(eqpt(findglenda(), Pt(-1, -1)))
|
||||
finished = Lost;
|
||||
}
|
||||
|
||||
int
|
||||
checkfinished(void)
|
||||
{
|
||||
int i, j;
|
||||
for(i = 0; i < SzX; i++)
|
||||
for(j = 0; j < SzY; j++)
|
||||
if(grid[i][j] == 'E')
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
move(Point m)
|
||||
{
|
||||
Point p, nm;
|
||||
int x, y;
|
||||
|
||||
nm = subpt(m, screen->r.min);
|
||||
|
||||
/* figure out where the click falls */
|
||||
p = pix2board(nm.x, nm.y);
|
||||
|
||||
if(grid[p.x][p.y] >= 999)
|
||||
return;
|
||||
|
||||
/* reset the board scores */
|
||||
grid[p.x][p.y] = 999;
|
||||
for(x = 0; x < SzX; x++)
|
||||
for(y = 0; y < SzY; y++)
|
||||
if(grid[x][y] != 999 && grid[x][y] != 1000)
|
||||
grid[x][y] = 100;
|
||||
|
||||
nextglenda();
|
||||
}
|
||||
|
||||
void
|
||||
resize(void)
|
||||
{
|
||||
int fd, size = (Dx(screen->r) > Dy(screen->r)) ? Dy(screen->r) + 20 : Dx(screen->r)+20;
|
||||
|
||||
fd = open("/dev/wctl", OWRITE);
|
||||
if(fd >= 0){
|
||||
fprint(fd, "resize -dx %d -dy %d", size, size);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
eresized(int new)
|
||||
{
|
||||
if(new && getwindow(display, Refnone) < 0)
|
||||
sysfatal("can't reattach to window");
|
||||
|
||||
drawlevel();
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
Mouse m;
|
||||
Event ev;
|
||||
int e, mousedown=0;
|
||||
char *fontname;
|
||||
|
||||
USED(argv, argc);
|
||||
|
||||
if(initdraw(nil, nil, "glendy") < 0)
|
||||
sysfatal("initdraw failed: %r");
|
||||
einit(Emouse);
|
||||
|
||||
resize();
|
||||
|
||||
srand(time(0));
|
||||
|
||||
allocimages();
|
||||
initlevel(); /* must happen before "eresized" */
|
||||
eresized(0);
|
||||
|
||||
fontname = "/lib/font/bit/lucidasans/unicode.8.font";
|
||||
if((font = openfont(display, fontname)) == nil)
|
||||
sysfatal("font '%s' not found", fontname);
|
||||
|
||||
for(;;) {
|
||||
e = event(&ev);
|
||||
switch(e) {
|
||||
case Emouse:
|
||||
m = ev.mouse;
|
||||
if(m.buttons == 0) {
|
||||
if(mousedown && !finished) {
|
||||
mousedown = 0;
|
||||
move(m.xy);
|
||||
drawlevel();
|
||||
}
|
||||
}
|
||||
if(m.buttons&1) {
|
||||
mousedown = 1;
|
||||
}
|
||||
if(m.buttons&2) {
|
||||
switch(emenuhit(2, &m, &mmenu)) {
|
||||
case 0:
|
||||
difficulty = DEasy;
|
||||
initlevel();
|
||||
break;
|
||||
case 1:
|
||||
difficulty = DMed;
|
||||
initlevel();
|
||||
break;
|
||||
case 2:
|
||||
difficulty = DHard;
|
||||
initlevel();
|
||||
break;
|
||||
}
|
||||
drawlevel();
|
||||
}
|
||||
if(m.buttons&4) {
|
||||
switch(emenuhit(3, &m, &rmenu)) {
|
||||
case 0:
|
||||
initlevel();
|
||||
break;
|
||||
case 1:
|
||||
memcpy(grid, ogrid, sizeof grid);
|
||||
finished = 0;
|
||||
break;
|
||||
case 2:
|
||||
exits(nil);
|
||||
}
|
||||
drawlevel();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ TARG=4s\
|
|||
life\
|
||||
memo\
|
||||
mole\
|
||||
glendy\
|
||||
|
||||
OFILES=
|
||||
HFILES=
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/rc
|
||||
window 0,0,161,117 stats -lmisce
|
||||
window
|
||||
window -scroll
|
||||
|
|
Loading…
Reference in a new issue