DIRECTORY Atom, Commander, Containers, FS, Graphics, GraphicsOps, IO, IOClasses, Labels, MazeWarFinder, MazeWarFinderRpcControl, MazeWarPlayer, MazeWarPlayerInsides, MazeWarPlayerRpcControl, MessageWindow, OrderedSymbolTableRef, Process, PupDefs, Random, Rope, RPC, UserCredentials, ViewerClasses, ViewerOps; MazeWarPlayerImpl2: CEDAR MONITOR IMPORTS Atom, Commander, Containers, FS, Graphics, GraphicsOps, IO, IOClasses, Labels, MazeWarFinder, MazeWarFinderRpcControl, MazeWarPlayerInsides, MazeWarPlayerRpcControl, MessageWindow, OSTR:OrderedSymbolTableRef, Process, PupDefs, Random, Rope, RPC, UserCredentials, ViewerOps EXPORTS MazeWarPlayer, MazeWarPlayerInsides = BEGIN OPEN MazeWarPlayerInsides; myself: PUBLIC Player _ NIL; myAddr: PUBLIC PupDefs.PupAddress; playerNumber: PUBLIC CARDINAL _ 47; myInstance: PUBLIC ROPE _ "??"; topviews: PUBLIC ARRAY Angle OF Bitmap _ ALL[NIL]; exportedPlayer: PUBLIC BOOLEAN _ FALSE; defaultPlayerPics: PUBLIC PlayerPics _ NEW [PlayerPicsRep _ [NIL, ALL[ALL[NIL]]]]; pieces: PUBLIC ARRAY [0 .. MaxDistance] OF ARRAY Piece OF LocatedBitmap _ ALL[ALL[[]]]; shownPlayers: PUBLIC PlayerList _ NIL; MakeNewPlayer: PUBLIC PROC [name, instance, picsSource, mazeSource: ROPE] RETURNS [errmsg: ROPE _ NIL] = BEGIN mv: MazeView; id: PlayerId _ Random.Choose[FIRST[INTEGER], LAST[INTEGER]]; userName, password, mazeRope: ROPE; failure: BOOLEAN _ FALSE; pp: PlayerPics; mazeStreamIn, mazeStreamOut: IO.STREAM; mazeStreamIn _ FS.StreamOpen[fileName: mazeSource ! FS.Error => {errmsg _ IO.PutFR["Unable to open maze source because %g", IO.rope[error.explanation]]; failure _ TRUE; CONTINUE}]; IF failure THEN RETURN; [] _ mazeStreamIn.SkipWhitespace[flushComments: FALSE]; mazeStreamOut _ IO.ROS[]; IOClasses.Copy[from: mazeStreamIn, to: mazeStreamOut, closeFrom: TRUE, closeTo: FALSE]; mazeRope _ mazeStreamOut.RopeFromROS[]; pp _ GetPlayerPics[picsSource ! FS.Error => {errmsg _ error.explanation; failure _ TRUE; CONTINUE}]; IF failure THEN RETURN; [mv, errmsg] _ MazeFromRope[mazeRope]; IF errmsg.Length[] > 0 THEN RETURN; myself _ Plop[mv, id, name, instance, pp]; ViewMaze[myself, [iconic: TRUE, name: name]]; AddScoring[myself, myself]; [userName, password] _ UserCredentials.Get[]; TRUSTED {MazeWarPlayerRpcControl.ExportInterface[ interfaceName: [instance: instance], user: userName, password: RPC.MakeKey[password]]}; exportedPlayer _ TRUE; TRUSTED {Process.Detach[FORK StayAlive[myself]]}; END; debugImport: BOOLEAN _ FALSE; importFailures: LIST OF CARDINAL _ NIL; exportedFinder: BOOLEAN _ FALSE; disabled: BOOL _ FALSE; finderID: BasicPlayer; StayAlive: PROC [p: Player] = BEGIN ENABLE UNWIND => {IF p.destroyed THEN myself _ NIL}; TRUSTED {Process.SetPriority[Process.priorityBackground]}; FOR age: CARDINAL _ 0, age + 1 WHILE NOT p.destroyed DO ok: BOOLEAN _ TRUE; IF NOT disabled THEN { MazeWarFinderRpcControl.ImportInterface[interfaceName: [instance: "MazeWar.Auto"] !RPC.ImportFailed => {ok _ FALSE; CONTINUE}]; IF debugImport THEN { MessageWindow.Append[IO.PutFR["Import %g at age %g", IO.bool[ok], IO.card[age]], TRUE]; IF NOT ok THEN importFailures _ CONS[age, importFailures]}; IF ok THEN { players: BasicPlayerList; TRUSTED { finderID _ MazeWarFinder.GetFinderID[!RPC.CallFailed => {ok _ FALSE; CONTINUE}]; IF ok THEN MazeWarFinder.TakePlayer[[myself.instanceName, myself.id] !RPC.CallFailed => {ok _ FALSE; CONTINUE}]; IF ok THEN players _ MazeWarFinder.ListPlayers[!RPC.CallFailed => {ok _ FALSE; CONTINUE}]}; IF ok THEN { FOR players _ players, players.rest WHILE players # NIL DO q: Player _ EnsurePlayer[players.first]; IF q # NIL AND NOT q.instanceName.Equal[players.first.instance] THEN MessageWindow.Append["Random number collision", TRUE]; ENDLOOP; }; MazeWarFinderRpcControl.UnimportInterface[]; } ELSE { IF exportedFinder THEN {MazeWarFinderRpcControl.UnexportInterface[]; exportedFinder _ FALSE}; TRUSTED {MazeWarFinderRpcControl.ExportInterface[ interfaceName: [instance: "MazeWar.Auto"], user: "MazeWar.Auto", password: RPC.MakeKey["MazeWar"]]}; exportedFinder _ TRUE; }; }; Delay[age]; ENDLOOP; IF exportedFinder THEN {MazeWarFinderRpcControl.UnexportInterface[]; exportedFinder _ FALSE}; myself _ NIL; END; WhoAmI: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = BEGIN p: Player _ myself; IF p = NIL THEN RETURN [$Failure, "Not playing"] ELSE cmd.out.PutF["\"%q\" %g\n", IO.rope[p.instanceName], IO.int[p.id]]; END; Contact: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = BEGIN Parse: PROC = { bp.instance _ in.GetRopeLiteral[]; bp.id _ in.GetInt[]; }; bp: BasicPlayer; in: IO.STREAM _ IO.RIS[cmd.commandLine]; ok: BOOL _ TRUE; IF myself = NIL THEN RETURN [$Failure, "Not playing"]; Parse[!IO.Error, IO.EndOfStream => { ok _ FALSE; CONTINUE}]; IF ok THEN [] _ EnsurePlayer[bp] ELSE RETURN [$Failure, "Syntax error; say: MazeWarContact \"nn#mmm#ss\" iiiii\n"]; END; Delay: PROC [age: CARDINAL] = BEGIN center: CARDINAL _ (IF age < 3 THEN 4 ELSE IF age < 16 THEN 16 ELSE 256) * Process.SecondsToTicks[1]; wait: CARDINAL _ Random.Choose[center/2, 3*center/2]; Process.Pause[wait]; END; MazeFromRope: PROC [rope: ROPE] RETURNS [mv: MazeView, errmsg: ROPE _ NIL] = BEGIN Check: PROC [row, col, drow, dcol: INTEGER] RETURNS [bad: BOOLEAN _ FALSE] = BEGIN index: INTEGER _ Index[mv, row-drow, col-dcol]; di: INTEGER _ Direction[mv, drow, dcol]; IF NOT mv.squares[index].open THEN BEGIN d: INTEGER _ 0; FOR index _ index+di, index+di WHILE mv.squares[index].open DO d _ d + 1 ENDLOOP; IF d > MaxDistance+1 THEN {errmsg _ IO.PutFR["Maze has open distance too long (> %g)", IO.int[MaxDistance+1]]; RETURN[TRUE]}; END; END; rl: INT _ rope.Length[]; cols: INTEGER _ rope.Find["\n"]; rows: INTEGER _ rl/(cols+1); IF rows*(cols+1) # rl THEN RETURN [NIL, "Maze description not properly punctuated with newlines"]; mv _ NEW [MazeViewRep[rows*cols]]; mv.asRope _ rope; mv.rows _ rows; mv.cols _ cols; FOR row: INTEGER IN [0 .. rows) DO FOR col: INTEGER IN [0 .. cols) DO char: CHAR _ rope.Fetch[row*(cols+1)+col]; index: INTEGER _ Index[mv, row, col]; mv.squares[index] _ []; SELECT char FROM 'X => mv.squares[index].open _ FALSE; '. => mv.squares[index].open _ TRUE; ENDCASE => RETURN [NIL, IO.PutFR["Bad character in maze: 0%bC", IO.char[char]]]; IF mv.squares[index].open AND (row = 0 OR row = rows-1 OR col = 0 OR col = cols-1) THEN RETURN [NIL, IO.PutFR["Gap in border"]]; ENDLOOP; ENDLOOP; FOR row: INTEGER IN (0 .. rows-1) DO FOR col: INTEGER IN (0 .. cols-1) DO IF Check[row, col, 0, 1] THEN RETURN; IF Check[row, col, 1, 0] THEN RETURN; ENDLOOP; ENDLOOP; mv.topX _ innerBorder + w - tvd*cols/2; mv.topY _ innerBorder + tvd*rows; mv.inY _ w + hallTopSep; mv.inX _ tvd*cols/2; END; hallTopSep: INTEGER _ 3; scoreTopSep: INTEGER _ 5; scoreSep: INTEGER _ 1; innerBorder: INTEGER _ 2; Plop: PROC [mv: MazeView, id: PlayerId, name, instance: ROPE, pp: PlayerPics] RETURNS [p: Player] = BEGIN row, col: INTEGER; [row, col] _ PickAPlace[mv]; p _ AddPlayerAt[mv, NIL, instance, id, name, row, col, 0, 0, pp]; END; PickAPlace: PUBLIC PROC [mv: MazeView] RETURNS [row, col: INTEGER] = BEGIN me: INTEGER; DO row _ Random.Choose[0, mv.rows-1]; col _ Random.Choose[0, mv.cols-1]; me _ Index[mv, row, col]; IF mv.squares[me].open THEN RETURN; ENDLOOP; END; ViewMaze: PROC [p: Player, viewerInit: ViewerClasses.ViewerRec] = BEGIN IF viewerInit.icon = unInit THEN viewerInit.icon _ mazeWarriorIcon; p.mv.container _ Containers.Create[info: viewerInit, paint: FALSE]; p.mv.maze _ ViewerOps.CreateViewer[flavor: mazeViewerFlavor, info: [parent: p.mv.container, wx: 10, wy: 10, ww: 100, wh: 100, data: p, border: FALSE], paint: FALSE]; ViewerOps.MoveViewer[ viewer: p.mv.maze, x: p.mv.maze.wx, y: p.mv.maze.wy, w: 2*(w+innerBorder) + p.mv.maze.ww - p.mv.maze.cw, h: 2*(w+innerBorder) + hallTopSep + tvd*p.mv.rows + p.mv.maze.wh - p.mv.maze.ch, paint: FALSE]; END; IncrPaint: PUBLIC PROC [p: Player] = { IF p.shot THEN TRUSTED {Process.Detach[FORK ReallyIncrPaint[p]]} ELSE ReallyIncrPaint[p]}; ReallyIncrPaint: PROC [p: Player] = { InnerPaint: ENTRY PROC = { ViewerOps.PaintViewer[viewer: p.mv.maze, hint: client, clearClient: FALSE, whatChanged: p]; }; IF p # myself OR NOT clippable THEN ViewerOps.PaintViewer[viewer: p.mv.maze, hint: client, clearClient: FALSE, whatChanged: p] ELSE { paints _ paints + 1; InnerPaint[!UNWIND => paints _ paints - 1]; paints _ paints - 1}; }; AddScoring: PUBLIC PROC [vp, p: Player] = BEGIN mv: MazeView _ p.mv; y: INTEGER _ vp.mv.maze.wy + vp.mv.maze.wh + scoreTopSep; p.nameLabel _ Labels.Create[info: [parent: mv.container, name: p.name, border: FALSE], paint: FALSE]; p.scoreLabel _ Labels.Create[info: [parent: mv.container, name: "-65,535", border: FALSE], paint: FALSE]; Labels.Set[p.scoreLabel, IO.PutFR["%6g", IO.int[p.score]], FALSE]; Labels.SetDisplayStyle[p.nameLabel, IF Visibility[vp, p] > 0 THEN $WhiteOnBlack ELSE $BlackOnWhite, FALSE]; FOR pl: PlayerList _ mv.players, pl.rest WHILE pl # NIL DO n: Viewer _ pl.first.nameLabel; v: Viewer _ pl.first.scoreLabel; ViewerOps.MoveViewer[viewer: n, x: mv.maze.wx, y: y, w: n.ww, h: n.wh, paint: FALSE]; ViewerOps.MoveViewer[viewer: v, x: mv.maze.wx + mv.maze.ww - v.ww, y: y, w: v.ww, h: v.wh, paint: FALSE]; y _ MAX[n.wy+n.wh, v.wy+v.wh] + scoreSep; ENDLOOP; END; DrawHall: PUBLIC PROC [context: Context, mv: MazeView, row, col, drow, dcol: INTEGER, angle: Angle] = BEGIN Line: PROC [a, b: Pt3] = INLINE { Graphics.SetCP[context, a.x/a.z, a.y/a.z]; Graphics.DrawTo[context, b.x/b.z, b.y/b.z]}; DoIt: PROC = { Blt: PROC [piece: Piece] = { lb: LocatedBitmap _ pieces[d][piece]; GraphicsOps.DrawBitmap[self: context, bitmap: lb.bitmap, w: lb.bitmap.width, h: lb.bitmap.height, x: 0, y: 0, xorigin: lb.xorigin, yorigin: lb.yorigin]; }; DrawPlayers: PROC = { Graphics.SetCP[context, 0, 0]; [] _ Graphics.SetPaintMode[context, invert]; FOR pl: PlayerList _ shownPlayers, pl.rest WHILE pl # NIL DO b: Bitmap _ pl.first.pics.pics[pl.first.sdistance][(pl.first.sangle+4-angle) MOD 4]; GraphicsOps.DrawBitmap[self: context, bitmap: b, w: b.width, h: b.height, x: 0, y: 0, xorigin: b.width/2, yorigin: b.height/2]; ENDLOOP; }; me, di, left, right, d, crow, ccol: INTEGER; f, b: Number; mes, lefts, rights: Square; di _ Direction[mv, drow, dcol]; left _ Direction[mv, -dcol, drow]; right _ Direction[mv, dcol, -drow]; crow _ row; ccol _ col; mes _ mv.squares[me _ Index[mv, row, col]]; f _ z1; b _ hither; [] _ Graphics.SetPaintMode[context, opaque]; Graphics.SetColor[context, Graphics.white]; Graphics.DrawBox[context, [-w, -w, w, w]]; Graphics.SetColor[context, Graphics.black]; Graphics.SetCP[context, w, w]; Graphics.DrawTo[context, w, -w]; Graphics.DrawTo[context, -w, -w]; Graphics.DrawTo[context, -w, w]; Graphics.DrawTo[context, w, w]; IF NOT mes.open THEN RETURN; lefts _ mv.squares[me + left]; rights _ mv.squares[me + right]; IF blt THEN { Graphics.SetCP[context, 0, 0]; [] _ Graphics.SetPaintMode[context, transparent]}; d _ 0; WHILE mes.open DO nu: INTEGER _ me + di; fls: Square _ mv.squares[nu + left]; frs: Square _ mv.squares[nu + right]; fs: Square _ mv.squares[nu]; r2: Number _ f*r/b; IF paints > 1 AND clippable THEN RETURN; IF NOT lefts.open THEN { IF blt THEN Blt[LeftFilled] ELSE { Line[[-r, r, f], [-r, r, b]]; Line[[-r, -r, f], [-r, -r, b]]}} ELSE IF NOT fls.open THEN { IF blt THEN Blt[LeftGap] ELSE { Line[[-r2, r, f], [-r, r, f]]; Line[[-r2, -r, f], [-r, -r, f]]}}; IF (IF fs.open THEN lefts.open # fls.open ELSE IF lefts.open THEN fls.open ELSE TRUE) THEN { IF blt THEN Blt[LeftEdge] ELSE Line[[-r, r, f], [-r, -r, f]]}; IF NOT rights.open THEN { IF blt THEN Blt[RightFilled] ELSE { Line[[ r, r, f], [ r, r, b]]; Line[[ r, -r, f], [ r, -r, b]]}} ELSE IF NOT frs.open THEN { IF blt THEN Blt[RightGap] ELSE { Line[[ r2, r, f], [ r, r, f]]; Line[[ r2, -r, f], [ r, -r, f]]}}; IF (IF fs.open THEN rights.open # frs.open ELSE IF rights.open THEN frs.open ELSE TRUE) THEN { IF blt THEN Blt[RightEdge] ELSE Line[[r, r, f], [r, -r, f]]}; b _ f; f _ f + dz; d _ d + 1; me _ nu; mes _ fs; lefts _ fls; rights _ frs; crow _ crow + drow; ccol _ ccol + dcol; ENDLOOP; d _ d - 1; IF blt THEN Blt[HorEdges] ELSE { Line[[-r, r, b], [r, r, b]]; Line[[-r, -r, b], [r, -r, b]]}; CallUnderMonitor1[DrawPlayers]; }; DoIt[]; END; AddPlayerAt: PUBLIC PROC [mv: MazeView, ir: PlayerInterface, instanceName: ROPE, id: PlayerId, name: ROPE, row, col: INTEGER, angle: Angle, score: INTEGER, pp: PlayerPics] RETURNS [p: Player] = BEGIN me: INTEGER _ Index[mv, row, col]; p _ NEW [PlayerRep _ [mv: mv, ir: ir, instanceName: instanceName, id: id, row: row, col: col, angle: angle, peek: 0, score: score, name: name, pics: pp]]; mv.squares[me].occupants _ CONS[p, mv.squares[me].occupants]; mv.players _ CONS[p, mv.players]; END; Rotate: PROC [x, y: REAL, angle: Angle] RETURNS [rx, ry: REAL] = BEGIN IF angle >= 2 THEN {x _ -x; y _ -y; angle _ angle-2}; IF angle = 0 THEN RETURN [x, y]; RETURN [-y, x]; END; picsTable: OSTR.Table _ OSTR.CreateTable[ComparePix]; ComparePix: OSTR.CompareProc--PROC [r1, r2: Item] RETURNS [Comparison]-- = BEGIN k1, k2: ROPE; WITH r1 SELECT FROM r: ROPE => k1 _ r; pp: PlayerPics => k1 _ pp.name; ENDCASE => ERROR; WITH r2 SELECT FROM r: ROPE => k2 _ r; pp: PlayerPics => k2 _ pp.name; ENDCASE => ERROR; RETURN [k1.Compare[s2: k2, case: FALSE]]; END; LosePlayerPics: PUBLIC ENTRY PROC [root: ROPE] = {[] _ picsTable.Delete[root]}; GetPlayerPics: PUBLIC PROC [root: ROPE] RETURNS [pp: PlayerPics] = BEGIN pp _ NARROW[picsTable.Lookup[root]]; IF pp = NIL THEN { newPics: PlayerPics _ ReadPlayerPics[root]; Insert: ENTRY PROC = { pp _ NARROW[picsTable.Lookup[root]]; IF pp = NIL THEN picsTable.Insert[pp _ newPics]}; Insert[]; }; END; ReadPlayerPics: PROC [root: ROPE] RETURNS [pp: PlayerPics] = BEGIN negate: BOOLEAN _ '- = root.Fetch[0]; IF myself # NIL THEN myself.pausing _ TRUE; MessageWindow.Append[Rope.Cat["Patience... loading images from ", root, " ..."], TRUE]; pp _ NEW [PlayerPicsRep _ [root, ALL[ALL[NIL]]]]; IF negate THEN root _ root.Substr[1, root.Length[]-1]; FOR a: Angle IN Angle DO image: GraphicsOps.ImageRef; xmin,ymin,xmax,ymax, imageSize, cx, cy: REAL; image _ GraphicsOps.NewAisImage[root.Cat[suffixes[a]]]; [xmin,ymin,xmax,ymax] _ GraphicsOps.ImageBox[image]; imageSize _ MAX[xmax-xmin, ymax-ymin]; cx _ (xmin+xmax)/2; cy _ (ymin+ymax)/2; FOR d: INTEGER IN [1 .. MaxDistance] DO rd: INTEGER _ r/(z1+(d-1)*dz); scale: REAL _ 2*rd/imageSize; context: Graphics.Context; mark: Graphics.Mark; pp.pics[d][a] _ GraphicsOps.NewBitmap[width: rd*2, height: rd*2]; context _ GraphicsOps.NewContextFromBitmap[pp.pics[d][a]]; Graphics.Translate[context, rd, rd]; IF negate THEN { Graphics.DrawBox[context, [-rd, -rd, rd, rd]]; mark _ Graphics.Save[context]}; Graphics.Scale[context, scale, scale]; Graphics.Translate[context, -cx, -cy]; Graphics.SetCP[context, 0, 0]; Graphics.DrawImage[context, image]; IF negate THEN { Graphics.Restore[context, mark]; [] _ Graphics.SetPaintMode[context, invert]; Graphics.DrawBox[context, [-rd, -rd, rd, rd]]}; ENDLOOP; ENDLOOP; MessageWindow.Append[" done", FALSE]; IF myself # NIL THEN myself.pausing _ FALSE; END; suffixes: ARRAY Angle OF ROPE _ ["Back.ais", "Right.ais", "Front.ais", "Left.ais"]; runMess: ROPE _ NIL; runError: BOOLEAN _ FALSE; Setup: PROC = BEGIN arrowPath: Graphics.Path _ Graphics.NewPath[8]; pp: Graphics.Path _ Graphics.NewPath[8]; f, b: Number; count: REF CARDINAL _ NARROW[Atom.GetProp[atom: $MazeWar, prop: $PlayerCount]]; playerRope: ROPE _ NIL; IF count = NIL THEN Atom.PutProp[atom: $MazeWar, prop: $PlayerCount, val: count _ NEW [CARDINAL _ 0]]; count^ _ playerNumber _ count^ + 1; TRUSTED {myAddr _ PupDefs.GetLocalPupAddress[[0, 0], [[0], [0], [0, 0]]]}; myInstance _ IO.PutFR["%b#%b#%b", IO.card[myAddr.net], IO.card[myAddr.host], IO.card[playerNumber]]; IF playerNumber # 1 THEN playerRope _ IO.PutFR["%g", IO.card[playerNumber]]; [] _ Random.Init[seed: -1]; {q: REAL = 2; q2: REAL = 5; Graphics.MoveTo[arrowPath, tvd/q, 0]; Graphics.LineTo[arrowPath, 0, tvd/q]; Graphics.LineTo[arrowPath, 0, tvd/q2]; Graphics.LineTo[arrowPath, -tvd/q, tvd/q2]; Graphics.LineTo[arrowPath, -tvd/q, -tvd/q2]; Graphics.LineTo[arrowPath, 0, -tvd/q2]; Graphics.LineTo[arrowPath, 0, -tvd/q]; Graphics.LineTo[arrowPath, tvd/q, 0]; }; FOR a: Angle IN Angle DO context: Context; topviews[a] _ GraphicsOps.NewBitmap[tvd, tvd]; context _ GraphicsOps.NewContextFromBitmap[topviews[a]]; Graphics.Translate[context, tvd/2, tvd/2]; Graphics.Rotate[context, a*-90]; Graphics.DrawArea[context, arrowPath]; --no more need for arrows, so commented out-- ENDLOOP; f _ z1; b _ hither; FOR d: INTEGER IN [0 .. MaxDistance] DO Start: PROC [piece: Piece] = { rmin: Number _ r/f; rmax: Number _ r/b; bounds: Box; bounds _ SELECT piece FROM LeftFilled => [-rmax, -rmax, -rmin, rmax], LeftGap => [-rmax, -rmin, -rmin, rmin], LeftEdge => [-rmin, -rmin, -rmin, rmin], RightFilled => [rmin, -rmax, rmax, rmax], RightGap => [rmin, -rmin, rmax, rmin], RightEdge => [rmin, -rmin, rmin, rmin], HorEdges => [-rmin, -rmin, rmin, rmin], ENDCASE => ERROR; bounds.xmin _ bounds.xmin - 1; bounds.ymin _ bounds.ymin - 1; bounds.xmax _ bounds.xmax + 1; bounds.ymax _ bounds.ymax + 1; pieces[d][piece] _ [ bitmap: GraphicsOps.NewBitmap[ width: bounds.xmax-bounds.xmin, height: bounds.ymax-bounds.ymin], xorigin: -bounds.xmin, yorigin: bounds.ymax]; context _ GraphicsOps.NewContextFromBitmap[pieces[d][piece].bitmap]; Graphics.Translate[context, -bounds.xmin, -bounds.ymin]; }; Line: PROC [a, b: Pt3] = INLINE { Graphics.SetCP[context, a.x/a.z, a.y/a.z]; Graphics.DrawTo[context, b.x/b.z, b.y/b.z]}; context: Graphics.Context; r2: Number _ f*r/b; Start[LeftFilled]; Line[[-r, r, f], [-r, r, b]]; Line[[-r, -r, f], [-r, -r, b]]; Start[LeftGap]; Line[[-r2, r, f], [-r, r, f]]; Line[[-r2, -r, f], [-r, -r, f]]; Start[LeftEdge]; Line[[-r, r, f], [-r, -r, f]]; Start[RightFilled]; Line[[ r, r, f], [ r, r, b]]; Line[[ r, -r, f], [ r, -r, b]]; Start[RightGap]; Line[[ r2, r, f], [ r, r, f]]; Line[[ r2, -r, f], [ r, -r, f]]; Start[RightEdge]; Line[[r, r, f], [r, -r, f]]; Start[HorEdges]; Line[[-r, r, f], [r, r, f]]; Line[[-r, -r, f], [r, -r, f]]; b _ f; f _ f + dz; ENDLOOP; ViewerOps.RegisterViewerClass[flavor: mazeViewerFlavor, class: mazeViewerClass]; Commander.Register[key: Rope.Cat["MazeWar", playerRope], proc: StartPlayer, doc: "starts playing maze war; see MazeWarDoc.Tioga for possible command line arguments"]; Commander.Register[key: Rope.Cat["MazeWarStop", playerRope], proc: StopPlayer, doc: "exits maze war game"]; Commander.Register[key: Rope.Cat["WhoAmI", playerRope], proc: WhoAmI, doc: "gives your MazeWar identification"]; Commander.Register[key: Rope.Cat["MazeWarContact", playerRope], proc: Contact, doc: "MazeWarContact \"nn#mmm#ss\" iiiii makes contact with that MazeWar player"]; END; Box: TYPE = RECORD [xmin, ymin, xmax, ymax: Number]; StupidFuckingWarnings: PUBLIC SIGNAL [ATOM] = CODE; Setup[]; END. Ί[Ivy]Top>MazeWar.df=>MazeWarPlayerImpl2.Mesa Last Edited by: Spreitzer, August 21, 1984 7:06:10 pm PDT INVARIANT No clippable paints are going on. mark: BasicTime.Pulses; IF hallHist # NIL THEN mark _ BasicTime.GetClockPulses[]; IF hallHist # NIL THEN hallHist.Increment[ BasicTime.PulsesToMicroseconds[BasicTime.GetClockPulses[] - mark]/5000]; hallHist: Histograms.Histogram; hallHistViewer: Viewer; HistHall: PROC = BEGIN hallHist _ Histograms.NewHistogram[]; hallHistViewer _ hallHist.ShowIn[name: "Hall Paint Times/(.005 sec)"]; END; IF root.Length[] < 1 OR root.Equal["default", FALSE] THEN RETURN [defaultPlayerPics]; no more-- [runMess, runError] _ CommandTool.Run["/Ivy/Spreitzer/Games/MazeWarCommon.BCD"]; FOR d: INTEGER IN [1 .. MaxDistance] DO Draw: PROC [x, z: REAL] = BEGIN y: REAL; [z, x] _ Rotate[z, x, a]; z _ ((z+1)*dz/2 + (d-1)*dz + z1)/r; y _ -1/z; x _ x/z; Graphics.LineTo[pp, x, y]; END; Move: PROC [x, z: REAL] = BEGIN y: REAL; [z, x] _ Rotate[z, x, a]; z _ ((z+1)*dz/2 + (d-1)*dz + z1)/r; y _ -1/z; x _ x/z; Graphics.MoveTo[pp, x, y]; END; context: Context; rd: INTEGER _ (s + d-1)/d; defaultPlayerPics.pics[d][a] _ GraphicsOps.NewBitmap[width: rd*2, height: rd*2]; context _ GraphicsOps.NewContextFromBitmap[defaultPlayerPics.pics[d][a]]; Graphics.Translate[context, rd, rd]; Move[0, 1]; Draw[-1, 0]; Draw[-.5, 0]; Draw[-.5, -1]; Draw[.5, -1]; Draw[.5, 0]; Draw[1, 0]; Draw[0, 1]; Graphics.DrawArea[context, pp]; ENDLOOP; ΚΖ– "cedar" style˜J™7J™9J˜codešΟk ˜ Kšœ8œΑœ,˜ͺ—K˜šΠbxœœ˜!Kšœ9œ{œ8œ˜˜Kšœ&˜-š ™ K™!——K˜Kšœœ˜ K˜Kšœœ œ˜K˜Kšœœ˜"Kšœœœ˜#Kšœ œœ˜K˜Kš œ œœœ œœ˜2K˜Kšœœœœ˜'K˜Kš œœœœœœœ˜RK˜Kšœœœœœœœœ˜WK˜Kšœœœ˜&K˜šΟn œœœ*œœ œœ˜hKš˜Kšœ ˜ Kš œœœœœ˜—šœœ œ˜Kšœœ˜šœ˜K˜K˜ ——šœœœ œ˜Kšœœ˜šœ˜K˜ K˜"——šœœ œœœ œ œœœ˜^Kšœœœ˜=—K˜K˜ K˜ K˜K˜ K˜ Kšœ ˜ K˜K˜Kšœ˜—K˜ Kšœœ˜šœ˜K˜K˜—K˜K˜—Kšœ™Kšœ œœ#™9Kšœ˜Kšœ œœ]™sKšœ˜—K˜K™K™K™K™šŸœœ™Kš™K™%K™FKšœ™—K˜šŸ œœœ3œœ œœœ˜ΑKš˜Kšœœ˜"Kšœœ“˜šKšœœ˜=Kšœ œ˜!Kšœ˜—K˜š Ÿœœœœ œ˜@Kš˜Kšœ œ#˜5Kšœ œœ˜ Kšœ ˜Kšœ˜—K˜Kšœ œ œ˜5K˜šŸ œœ  ,œ˜JKš˜Kšœœ˜ šœœ˜Kšœœ ˜K˜Kšœœ˜—šœœ˜Kšœœ ˜K˜Kšœœ˜—Kšœœ˜)Kšœ˜—K˜Kš Ÿœœœœœ"˜OK˜š Ÿ œœœœœ˜BKš˜Kšœ_™_Kšœœ˜$šœœœ˜Kšœ+˜+šŸœœœ˜Kšœœ˜$Kšœœœ!˜1—Kšœ ˜ K˜—Kšœ˜—K˜šŸœœœœ˜