diff options
Diffstat (limited to 'appl/lib/gamer.b')
| -rw-r--r-- | appl/lib/gamer.b | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/appl/lib/gamer.b b/appl/lib/gamer.b new file mode 100644 index 00000000..bb38ddbe --- /dev/null +++ b/appl/lib/gamer.b @@ -0,0 +1,147 @@ +implement Gamer; + +include "sys.m"; +include "gamer.m"; + +sys: Sys; +FD, Connection: import Sys; + +devsysname: con "/dev/sysname"; + +addr: string; +stderr: ref FD; + +getaddr() : int +{ + f := sys->open(devsysname, sys->OREAD); + if (f == nil) { + sys->fprint(stderr, "open %s failed: %r\n", devsysname); + return -1; + } + buff := array[64] of byte; + n := sys->read(f, buff, len buff); + if (n < 0) { + sys->fprint(stderr, "read %s failed: %r\n", devsysname); + return -1; + } + addr = "tcp!" + string buff[0:n] + "!gamed"; + return 0; +} + +Join(game: string) : Game +{ + g: Game; + + g.player = -1; + if(sys == nil) { + sys = load Sys Sys->PATH; + stderr = sys->fildes(2); + + if (getaddr() < 0) + return g; + } + + (ok, c) := sys->dial(addr, nil); + if (ok < 0) { + sys->fprint(stderr, "dial %s failed: %r\n", addr); + return g; + } + + s := "join " + game; + b := array of byte s; + if (sys->write(c.dfd, b, len b) < 0) { + sys->fprint(stderr, "write %s failed: %r\n", addr); + return g; + } + + buff := array[64] of byte; + n := sys->read(c.dfd, buff, len buff); + if (n < 0) { + sys->fprint(stderr, "read %s failed: %r\n", addr); + return g; + } + if (n == 0) { + sys->fprint(stderr, "eof on read %s\n", addr); + return g; + } + s = string buff[0:n]; + if (s == "error") { + sys->fprint(stderr, "%s returns error\n", addr); + return g; + } + c.dfd = nil; + (t, l) := sys->tokenize(s, " \t\n"); + if (t != 3) { + sys->fprint(stderr, "%s returns bad response\n", addr); + return g; + } + g.opponent = hd tl l; + player := int hd tl tl l; + s = "local " + s; + + (ok, c) = sys->dial(addr, nil); + if (ok < 0) { + sys->fprint(stderr, "dial %s failed: %r\n", addr); + return g; + } + b = array of byte s; + if (sys->write(c.dfd, b, len b) < 0) { + sys->fprint(stderr, "write %s failed: %r\n", addr); + return g; + } + n = sys->read(c.dfd, buff, len buff); + if (n < 0) { + sys->fprint(stderr, "read %s failed: %r\n", addr); + return g; + } + g.wf = c.dfd; + if (n == 0) { + sys->fprint(stderr, "eof on read %s\n", addr); + return g; + } + s = string buff[0:n]; + if (s == "error") { + sys->fprint(stderr, "%s returns error\n", addr); + return g; + } + g.rf = sys->open(s, sys->OREAD); + if (g.rf == nil) { + sys->fprint(stderr, "pipe open %s failed: %r\n", s); + return g; + } + g.player = player; + return g; +} + +Game.In(g: self Game) : int +{ + buff := array[1] of byte; + + if ((rd := sys->read(g.rf, buff, 1)) == 1) + return int buff[0]; + + if (rd < 0) + sys->fprint(stderr, "gamed read failed: %r\n"); + + g.rf = nil; + return -1; +} + +Game.Out(g: self Game, i: int) +{ + buff := array[1] of byte; + + buff[0] = byte i; + if (sys->write(g.wf, buff, 1) != 1) { + sys->fprint(stderr, "gamed write failed: %r\n"); + g.wf = nil; + return; + } +} + +Game.Exit(g: self Game) +{ + g.Out(255); + g.rf = nil; + g.wf = nil; +} |
