From 8285721acfc247d57e0831503543dd29290ac4c5 Mon Sep 17 00:00:00 2001 From: rodri Date: Sat, 12 Aug 2023 05:35:54 +0000 Subject: latest try of player mgmt procedure. (not working) --- bts.c | 108 ++++++++++++++++++++++++++++++---- btsd.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- dat.h | 39 +++++++++++++ 3 files changed, 314 insertions(+), 40 deletions(-) diff --git a/bts.c b/bts.c index b777819..4f636a6 100644 --- a/bts.c +++ b/bts.c @@ -13,12 +13,17 @@ int debug; char deffont[] = "/lib/font/bit/pelm/unicode.9.font"; char winspec[32]; Channel *drawchan; +Channel *ingress, *egress; RFrame worldrf; Image *screenb; Image *tiletab[NTILES]; Board alienboard; Board localboard; +struct { + int state; +} game; + Point fromworld(Point2 p) @@ -177,12 +182,40 @@ initboards(void) alienboard.p = Pt2(Boardmargin,Boardmargin,1); memset(localboard.map, Twater, MAPW*MAPH); localboard.p = addpt2(alienboard.p, Vec2(0,MAPH*TH+TH)); - alienboard.bx = localboard.bx = Vec2(TW,0); - alienboard.by = localboard.by = Vec2(0,TH); + alienboard.bx = Vec2(TW,0); + localboard.bx = Vec2(TW,0); + alienboard.by = Vec2(0,TH); + localboard.by = Vec2(0,TH); alienboard.bbox = Rpt(fromworld(alienboard.p), fromworld(addpt2(alienboard.p, Pt2(TW*MAPW,TH*MAPH,1)))); localboard.bbox = Rpt(fromworld(localboard.p), fromworld(addpt2(localboard.p, Pt2(TW*MAPW,TH*MAPH,1)))); } +void +lmb(Mousectl *mc) +{ + Board *b; + Point2 cell; + + b = nil; + if(ptinrect(mc->xy, alienboard.bbox)) + b = &alienboard; + else if(ptinrect(mc->xy, localboard.bbox)) + b = &localboard; + + if(b != nil){ + cell = toboard(b, mc->xy); + switch(game.state){ + case Outlaying: + settile(b, cell, Tship); + case Playing: + settile(b, cell, Tmiss); + chanprint(egress, "shoot %d-%d", (int)cell.x, (int)cell.y); + break; + } + } + send(drawchan, nil); +} + void mouse(Mousectl *mc) { @@ -190,15 +223,13 @@ mouse(Mousectl *mc) switch(mc->buttons){ case 1: - if(ptinrect(mc->xy, alienboard.bbox)) - settile(&alienboard, toboard(&alienboard, mc->xy), Tmiss); - if(ptinrect(mc->xy, localboard.bbox)) - settile(&localboard, toboard(&localboard, mc->xy), Tmiss); - send(drawchan, nil); + lmb(mc); break; case 2: + //mmb(mc); break; - case 3: + case 4: + //rmb(mc); break; } } @@ -233,13 +264,15 @@ inputthread(void *arg) in = arg; - a[0].op = CHANRCV; a[0].c = in->mc->c; a[0].v = &in->mc->Mouse; - a[1].op = CHANRCV; a[1].c = in->mc->resizec; a[1].v = nil; - a[2].op = CHANRCV; a[2].c = in->kc->c; a[2].v = &r; + a[0].c = in->mc->c; a[0].v = &in->mc->Mouse; a[0].op = CHANRCV; + a[1].c = in->mc->resizec; a[1].v = nil; a[1].op = CHANRCV; + a[2].c = in->kc->c; a[2].v = &r; a[2].op = CHANRCV; a[3].op = CHANEND; for(;;) switch(alt(a)){ + case -1: + sysfatal("input thread interrupted"); case 0: mouse(in->mc); break; @@ -252,6 +285,51 @@ inputthread(void *arg) } } +void +netrecvthread(void *arg) +{ + Ioproc *io; + char buf[256]; + int n, fd; + + threadsetname("netrecvthread"); + + fd = *(int*)arg; + io = ioproc(); + + while((n = ioread(io, fd, buf, sizeof(buf)-1)) > 0){ + buf[n] = 0; + if(debug) + fprint(2, "rcvd '%s'\n", buf); + if(strcmp(buf, "wait") == 0) + game.state = Waiting1; + else if(strcmp(buf, "play") == 0) + game.state = Playing; +// chanprint(ingress, "%s", buf); + } + closeioproc(io); + threadexitsall("connection lost"); +} + +void +netsendthread(void *arg) +{ + char *s; + int fd; + + threadsetname("netsendthread"); + + fd = *(int*)arg; + + while(recv(egress, &s) > 0){ + if(write(fd, s, strlen(s)) != strlen(s)) + break; + if(debug) + fprint(2, "sent '%s'\n", s); + } + threadexitsall("connection lost"); +} + void usage(void) { @@ -286,6 +364,9 @@ threadmain(int argc, char *argv[]) else if(debug) fprint(2, "line established\n"); + if(write(fd, "join", 4) != 4) + sysfatal("whoops: %r"); + snprint(winspec, sizeof winspec, "-dx %d -dy %d", SCRW, SCRH); if(newwindow(winspec) < 0) sysfatal("newwindow: %r"); @@ -306,10 +387,15 @@ threadmain(int argc, char *argv[]) inittiles(); initboards(); + game.state = Waiting0; drawchan = chancreate(sizeof(void*), 0); + ingress = chancreate(sizeof(char*), 0); + egress = chancreate(sizeof(char*), 0); proccreate(showproc, nil, mainstacksize); threadcreate(inputthread, &in, mainstacksize); + threadcreate(netrecvthread, &fd, mainstacksize); + threadcreate(netsendthread, &fd, mainstacksize); send(drawchan, nil); yield(); } diff --git a/btsd.c b/btsd.c index 5d5161a..7cbd283 100644 --- a/btsd.c +++ b/btsd.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -10,44 +9,182 @@ #include "fns.h" int debug; +int mainstacksize = 16*KB; +Playerq playerq; + + +void +pushplayer(Player *p) +{ + qlock(&playerq); + if(++playerq.nplayers > playerq.cap){ + playerq.cap = playerq.nplayers; + playerq.players = erealloc(playerq.players, playerq.cap * sizeof p); + } + playerq.players[playerq.nplayers-1] = p; + qunlock(&playerq); +} + +Player * +popplayer(void) +{ + Player *p; + + p = nil; + if(playerq.nplayers > 0){ + qlock(&playerq); + p = playerq.players[--playerq.nplayers]; + qunlock(&playerq); + } + return p; +} + +void +netrecvthread(void *arg) +{ + Chanpipe *cp; + Ioproc *io; + char buf[256]; + int n; + + cp = arg; + io = ioproc(); + + while((n = ioread(io, cp->fd, buf, sizeof(buf)-1)) > 0){ + buf[n] = 0; + chanprint(cp->c, "%s", buf); + } + chanclose(cp->c); + if(debug) + fprint(2, "[%d] %d lost connection\n", threadpid(threadid()), threadid()); +} void serveproc(void *arg) { - Biobuf *bin, *bout; - NetConnInfo *nci; - char *line; - int fd, linelen; - - fd = *(int*)arg; - nci = getnetconninfo(nil, fd); - if(nci == nil) + NetConnInfo *nci[2]; + Player **m; + Chanpipe *cp; + Alt a[3]; + int i, n0; + char *s; + + threadsetname("serveproc "); + + m = arg; + s = nil; + + nci[0] = getnetconninfo(nil, m[0]->fd); + nci[1] = getnetconninfo(nil, m[1]->fd); + if(nci[0] == nil || nci[1] == nil) sysfatal("getnetconninfo: %r"); - threadsetname("serveproc %s", nci->raddr); - freenetconninfo(nci); - - bin = Bfdopen(fd, OREAD); - bout = Bfdopen(fd, OWRITE); - if(bin == nil || bout == nil) - sysfatal("Bfdopen: %r"); - - while((line = Brdline(bin, '\n')) != nil){ - linelen = Blinelen(bin); - Bwrite(bout, line, linelen); - Bflush(bout); - print("%.*s", linelen, line); + threadsetname("serveproc %s ↔ %s", nci[0]->raddr, nci[1]->raddr); + freenetconninfo(nci[0]); + freenetconninfo(nci[1]); + + cp = emalloc(2*sizeof(Chanpipe)); + cp[0].c = chancreate(sizeof(char*), 1); + cp[0].fd = m[0]->fd; + cp[1].c = chancreate(sizeof(char*), 1); + cp[1].fd = m[1]->fd; + + a[0].c = cp[0].c; a[0].v = &s; a[0].op = CHANRCV; + a[1].c = cp[1].c; a[1].v = &s; a[1].op = CHANRCV; + a[2].op = CHANEND; + + threadcreate(netrecvthread, &cp[0], mainstacksize); + threadcreate(netrecvthread, &cp[1], mainstacksize); + + n0 = truerand(); + write(m[n0%2]->fd, "wait", 4); + write(m[(n0+1)%2]->fd, "play", 4); + + while((i = alt(a)) >= 0){ + if(debug) + fprint(2, "[%d] %d said '%s'\n", threadpid(threadid()), threadid(), s); + if(a[i].err != nil){ + write(m[i^1]->fd, "won", 3); + /* TODO free the player */ + pushplayer(m[i^1]); + goto out; + } + if(write(m[i^1]->fd, s, strlen(s)) != strlen(s)){ + write(m[i]->fd, "won", 3); + /* TODO free the player */ + pushplayer(m[i]); + goto out; + } + free(s); + } +out: + if(debug) + fprint(2, "[%d] serveproc ending\n", threadpid(threadid())); + chanclose(cp[0].c); + chanclose(cp[1].c); + /* TODO make sure this is the last thread to exit */ +// recv(cp[0].done) +// recv(cp[1].done) + free(m); +} + +void +reaper(void *) +{ + Ioproc *io; + char buf[8]; + ulong i; + int n; + + threadsetname("reaper"); + + io = ioproc(); + + for(;;){ + for(i = 0; i < playerq.nplayers; i++){ + n = read(playerq.players[i]->sfd, buf, sizeof buf); + if(n < 0 || strncmp(buf, "Closed", 6) == 0){ + qlock(&playerq); + close(playerq.players[i]->fd); + close(playerq.players[i]->sfd); + free(playerq.players[i]); + memmove(&playerq.players[i], &playerq.players[i+1], (--playerq.nplayers-i)*sizeof(Player*)); + qunlock(&playerq); + } + } + iosleep(io, HZ2MS(3)); } +} + +void +matchmaker(void *) +{ + Player **match; + + threadsetname("matchmaker"); - Bterm(bin); - Bterm(bout); + for(;;){ + if(playerq.nplayers < 2){ + sleep(100); + continue; + } + + match = emalloc(2*sizeof(Player*)); + match[0] = popplayer(); + match[1] = popplayer(); + match[1]->o = match[0]; + match[0]->o = match[1]; + + proccreate(serveproc, match, mainstacksize); + } } void listenthread(void *arg) { - char *addr, adir[40], ldir[40]; - int acfd, lcfd, dfd; + char *addr, adir[40], ldir[40], aux[128], *s; + int acfd, lcfd, dfd, sfd; + Player *p; addr = arg; @@ -57,11 +194,21 @@ listenthread(void *arg) if(debug) fprint(2, "listening on %s\n", addr); - + while((lcfd = listen(adir, ldir)) >= 0){ if((dfd = accept(lcfd, ldir)) >= 0){ - proccreate(serveproc, &dfd, mainstacksize); - close(dfd); + fd2path(dfd, aux, sizeof aux); + s = strrchr(aux, '/'); + *s = 0; + snprint(aux, sizeof aux, "%s/status", aux); + sfd = open(aux, OREAD); + if(sfd < 0) + sysfatal("open: %r"); + + p = emalloc(sizeof *p); + p->fd = dfd; + p->sfd = sfd; + pushplayer(p); } close(lcfd); } @@ -94,5 +241,7 @@ threadmain(int argc, char *argv[]) usage(); threadcreate(listenthread, addr, mainstacksize); + proccreate(matchmaker, nil, mainstacksize); + proccreate(reaper, nil, mainstacksize); yield(); } diff --git a/dat.h b/dat.h index b0350e1..2a2c6b5 100644 --- a/dat.h +++ b/dat.h @@ -5,6 +5,11 @@ enum { Tmiss, NTILES, + Waiting0 = 0, + Outlaying, + Waiting1, + Playing, + Boardmargin = 50, TW = 16, TH = TW, @@ -12,10 +17,16 @@ enum { MAPH = MAPW, SCRW = Boardmargin+MAPW*TW+Boardmargin, SCRH = Boardmargin+MAPH*TH+TH+MAPH*TH+Boardmargin, + + KB = 1024, }; typedef struct Input Input; typedef struct Board Board; +typedef struct Ship Ship; +typedef struct Player Player; +typedef struct Playerq Playerq; +typedef struct Chanpipe Chanpipe; struct Input { @@ -29,3 +40,31 @@ struct Board char map[17][17]; Rectangle bbox; }; + +struct Ship +{ + RFrame; + int ncells; + int sunk; +}; + +struct Player +{ + int fd; + int sfd; + Player *o; /* opponent */ +}; + +struct Playerq +{ + QLock; + Player **players; + ulong cap; + ulong nplayers; +}; + +struct Chanpipe +{ + Channel *c; + int fd; +}; -- cgit v1.2.3