diff options
Diffstat (limited to 'appl/spree/engines/bounce.b')
| -rw-r--r-- | appl/spree/engines/bounce.b | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/appl/spree/engines/bounce.b b/appl/spree/engines/bounce.b new file mode 100644 index 00000000..05e476d4 --- /dev/null +++ b/appl/spree/engines/bounce.b @@ -0,0 +1,258 @@ +implement Gatherengine; + +include "sys.m"; + sys: Sys; +include "draw.m"; + draw: Draw; + Point, Rect: import draw; +include "sets.m"; + sets: Sets; + Set, All, None, A, B: import sets; +include "../spree.m"; + spree: Spree; + Attributes, Range, Object, Clique, Member: import spree; +include "../gather.m"; + +clique: ref Clique; + +W, H: con 500; +INSET: con 20; +D: con 30; +BATLEN: con 100.0; +GOALSIZE: con 0.1; + +MAXPLAYERS: con 32; +nmembers := 0; + +Line: adt { + p1, p2: Point; + seg: fn(l: self Line, s1, s2: real): Line; +}; + +Dmember: adt { + p: ref Member; + score: int; + bat: ref Object; +}; + +Eusage: con "bad command usage"; +colours := array[4] of {"blue", "orange", "yellow", "white"}; +batpos: array of Line; +borderpos: array of Line; + +members: array of Dmember; +arena: ref Object; +clienttype(): string +{ + return "bounce"; +} + +maxmembers(): int +{ + return 4; +} + +readfile(nil: int, nil: big, nil: int): array of byte +{ + return nil; +} + +init(srvmod: Spree, g: ref Clique, nil: list of string, nil: int): string +{ + sys = load Sys Sys->PATH; + draw = load Draw Draw->PATH; + clique = g; + spree = srvmod; + + sets = load Sets Sets->PATH; + if (sets == nil) { + sys->print("spit: cannot load %s: %r\n", Sets->PATH); + return "bad module"; + } + sets->init(); + + r := Rect((0, 0), (W, H)); + walls := sides(r.inset(INSET)); + addlines(segs(walls, 0.0, 0.5 - GOALSIZE), nil); + addlines(segs(walls, 0.5 + GOALSIZE, 1.0), nil); + + batpos = l2a(segs(sides(r.inset(INSET + 50)), 0.1, 0.9)); + borderpos = l2a(sides(r.inset(-1))); + + arena = clique.newobject(nil, All, "arena"); + arena.setattr("arenasize", string W + " " + string H, All); + + return nil; +} + +propose(members: array of string): string +{ + if (len members < 2) + return "need at least two members"; + if (len members > 4) + return "too many members"; + return nil; +} + +archive() +{ +} + +start(pl: array of ref Member, archived: int) +{ + if (archived) { + } else { + members = array[len pl] of Dmember; + for (i := 0; i < len pl; i++) { + p := pl[i]; + bat := addline(batpos[i], nil); + bat.setattr("pos", "10 " + string (10.0 + BATLEN), All); + bat.setattr("owner", p.name, All); + addline(borderpos[i], ("owner", p.name) :: nil); + arena.setattr("member" + string i, p.name + " " + colours[i], All); + members[i] = (p, 0, bat); + } + r := Rect((0, 0), (W, H)).inset(INSET + 1); + goals := l2a(sides(r)); + for (i = len members; i < len batpos; i++) { + addline(goals[i], nil); + addline(borderpos[i], ("owner", pl[0].name) :: nil); + } + } +} + +addline(lp: (Point, Point), attrs: list of (string, string)): ref Object +{ + (p1, p2) := lp; + l := clique.newobject(nil, All, "line"); + l.setattr("coords", p2s(p1) + " " + p2s(p2), All); + l.setattr("id", string l.id, All); + for (; attrs != nil; attrs = tl attrs) { + (attr, val) := hd attrs; + l.setattr(attr, val, All); + } + return l; +} + + +p2s(p: Point): string +{ + return string p.x + " " + string p.y; +} + +command(member: ref Member, cmd: string): string +{ + ord := order(member); + sys->print("cmd: %s", cmd); + { + (n, toks) := sys->tokenize(cmd, " \n"); + assert(n > 0, "unknown command"); + case hd toks { + "newball" => + # newball batid p.x p.y v.x v.y speed + assert(n == 7, Eusage); + bat := member.obj(int hd tl toks); + assert(bat != nil, "no such bat"); + ball := clique.newobject(nil, All, "ball"); + ball.setattr("state", string bat.id + " " + string ord + + " " + concat(tl tl toks) + " " + string sys->millisec(), All); + "lost" => + # lost ballid + assert(n == 2, Eusage); + o := member.obj(int hd tl toks); + assert(o != nil, "bad object"); + assert(o.getattr("state") != nil, "can only lose balls"); + o.delete(); + "state" => + # state ballid lasthit owner p.x p.y v.x v.y s time + assert(n == 10, Eusage); + assert(ord >= 0, "you are not playing"); + o := member.obj(int hd tl toks); + assert(o != nil, "object does not exist"); + o.setattr("state", concat(tl tl toks), All); + members[ord].score++; + arena.setattr("score" + string ord, string members[ord].score, All); + "bat" => + # bat pos + assert(n == 2, Eusage); + s1 := real hd tl toks; + members[ord].bat.setattr("pos", hd tl toks + " " + string (s1 + BATLEN), All); + "time" => + # time millisec + assert(n == 2, Eusage); + tm := int hd tl toks; + offset := sys->millisec() - tm; + clique.action("time " + string offset + " " + string tm, nil, nil, None.add(member.id)); + * => + assert(0, "bad command"); + } + } exception e { + "parse:*" => + return e[6:]; + } + return nil; +} + +order(p: ref Member): int +{ + for (i := 0; i < len members; i++) + if (members[i].p == p) + return i; + return -1; +} + +assert(b: int, err: string) +{ + if (b == 0) + raise "parse:" + err; +} + +concat(v: list of string): string +{ + if (v == nil) + return nil; + s := hd v; + for (v = tl v; v != nil; v = tl v) + s += " " + hd v; + return s; +} + +Line.seg(l: self Line, s1, s2: real): Line +{ + (dx, dy) := (l.p2.x - l.p1.x, l.p2.y - l.p1.y); + return (((l.p1.x + int (s1 * real dx)), l.p1.y + int (s1 * real dy)), + ((l.p1.x + int (s2 * real dx)), l.p1.y + int (s2 * real dy))); +} + +sides(r: Rect): list of Line +{ + return ((r.min.x, r.min.y), (r.min.x, r.max.y)) :: + ((r.max.x, r.min.y), (r.max.x, r.max.y)) :: + ((r.min.x, r.min.y), (r.max.x, r.min.y)) :: + ((r.min.x, r.max.y), (r.max.x, r.max.y)) :: nil; +} + +addlines(ll: list of Line, attrs: list of (string, string)) +{ + for (; ll != nil; ll = tl ll) + addline(hd ll, attrs); +} + +segs(ll: list of Line, s1, s2: real): list of Line +{ + nll: list of Line; + for (; ll != nil; ll = tl ll) + nll = (hd ll).seg(s1, s2) :: nll; + ll = nil; + for (; nll != nil; nll = tl nll) + ll = hd nll :: ll; + return ll; +} + +l2a(ll: list of Line): array of Line +{ + a := array[len ll] of Line; + for (i := 0; ll != nil; ll = tl ll) + a[i++] = hd ll; + return a; +} |
