DIRECTORY FS USING [StreamOpen, Error], FootballInternal, FootballMaster, InputFocus USING [SetInputFocus], IO USING [Close, int, EndOf, EndOfStream, GetInt, GetLineRope, GetTokenRope, IDProc, Put, Put1, PutF, RIS, rope, STREAM], Menus USING [AppendMenuEntry, ClickProc, CreateEntry, FindEntry, Menu, MenuLine, ReplaceMenuEntry], MessageWindow USING [Append, Blink, Clear], Process USING [SetTimeout], Real USING [Round], Rope USING [Equal, Length, ROPE], ViewerClasses USING [MenuEntry], ViewerOps USING [PaintViewer, SetMenu], ViewerTools USING [MakeNewTextViewer]; FootballPlays: MONITOR IMPORTS FS, FootballInternal, FootballMaster, InputFocus, IO, Menus, MessageWindow, Process, Real, Rope, ViewerOps, ViewerTools EXPORTS FootballInternal SHARES ViewerClasses = { OPEN FootballInternal, FootballMaster; delay: CARDINAL _ 1; InitPlays: PUBLIC PROC[t: T] = { t.current _ NEW[PlayRec _ []]; t.planned _ NEW[PlayRec _ []]; }; WritePlayBook: PUBLIC PROC[t: T, name: Rope.ROPE] = TRUSTED { OPEN IO; ENABLE FS.Error => {MessageWindow.Append["failed."]; CONTINUE}; stream: IO.STREAM; IF name.Length[] = 0 THEN RETURN; MessageWindow.Append["Writing plays on ", TRUE]; MessageWindow.Append[name]; MessageWindow.Append[". . . "]; stream _ FS.StreamOpen[name, create]; stream.Put[rope["-- "], rope[name], rope["\n"]]; stream.Put1[rope["-- playname: {offensive | defensive} {setup | play}\n"]]; stream.Put1[rope["-- {player}: {stop | run | block | guard} {target}\n"]]; stream.Put1[rope["-- ball: {pass | kick} {target}\n"]]; stream.Put1[rope["-- player = {QB | LE | RE | LG | RG | C}\n"]]; stream.Put1[rope["-- target = {null | goal | ball | {player} | location x y (relative to scrimmage)}\n\n"]]; FOR i: Menus.MenuLine IN [1..t.viewer.menu.linesUsed) DO FOR entry: ViewerClasses.MenuEntry _ t.viewer.menu.lines[i], entry.link WHILE entry # NIL DO WritePlay[t, stream, NARROW[entry.clientData]]; ENDLOOP; ENDLOOP; stream.Close[]; MessageWindow.Append["done."]; [] _ ViewerTools.MakeNewTextViewer[[name: name, file: name, iconic: FALSE]]; }; WritePlay: PROC[t: T, stream: IO.STREAM, play: Play] = { OPEN IO, Real; action: Action; target: Target; stream.Put[rope[play.name], rope[": "]]; stream.Put1[rope[IF play.side = offense THEN "offensive" ELSE "defensive"]]; stream.Put[rope[IF play.setUp THEN " setup" ELSE " play"], rope["\n"]]; FOR i: CARDINAL IN [0..6] DO IF i = 6 THEN { IF play.setUp OR play.side = defense THEN LOOP; action _ play.ball.action; target _ play.ball.target; IF action = stop THEN LOOP; stream.Put1[rope["ball:"]]} ELSE { stream.Put[rope[PositionName[Add[HQB, i]]], rope[":"]]; action _ play.commands[i].action; target _ play.commands[i].target}; SELECT action FROM stop => stream.Put1[rope[" stop"]]; run => stream.Put1[rope[" run"]]; block => stream.Put1[rope[IF play.side = offense THEN " block" ELSE " guard"]]; pass => stream.Put1[rope[" pass"]]; kick => stream.Put1[rope[" kick"]]; ENDCASE => ERROR; IF target.type = absolute THEN target _ Translate[t, target, t.myTeam]; WITH t: target SELECT FROM null => stream.Put1[rope["\n"]]; goal => stream.Put1[rope[" goal\n"]]; player => IF t.position = ball THEN stream.Put1[rope[" ball\n"]] ELSE stream.Put[rope[" "], rope[PositionName[t.position]], rope["\n"]]; relative => stream.PutF[" location %g %g\n", int[Round[t.x]], int[Round[t.y]]]; ENDCASE => ERROR; ENDLOOP; stream.Put1[rope["\n"]]; }; PositionName: PROC[player: Position] RETURNS[Rope.ROPE] = { SELECT player FROM VQB, HQB => RETURN["QB"]; VLE, HLE => RETURN["LE"]; VRE, HRE => RETURN["RE"]; VLG, HLG => RETURN["LG"]; VRG, HRG => RETURN["RG"]; VC, HC => RETURN["C"]; ENDCASE => RETURN["ball"]; }; ReadPlayBook: PUBLIC PROC[t: T, name: Rope.ROPE] = TRUSTED { ENABLE FS.Error => {MessageWindow.Append["failed."]; CONTINUE}; play: Play; line, token: Rope.ROPE; stream, file: IO.STREAM; IF name.Length[] = 0 THEN RETURN; MessageWindow.Append["Reading plays from ", TRUE]; MessageWindow.Append[name]; MessageWindow.Append[". . . "]; file _ FS.StreamOpen[name]; WHILE ~file.EndOf[] DO ENABLE IO.EndOfStream => LOOP; line _ file.GetLineRope[]; -- reads but doesn't return CR stream _ IO.RIS[line, stream]; token _ stream.GetTokenRope[IO.IDProc].token; SELECT TRUE FROM Rope.Equal[token, "--"] => LOOP; Rope.Equal[token, "QB"] => play.commands[0] _ ReadCommand[t, stream]; Rope.Equal[token, "LE"] => play.commands[1] _ ReadCommand[t, stream]; Rope.Equal[token, "RE"] => play.commands[2] _ ReadCommand[t, stream]; Rope.Equal[token, "LG"] => play.commands[3] _ ReadCommand[t, stream]; Rope.Equal[token, "RG"] => play.commands[4] _ ReadCommand[t, stream]; Rope.Equal[token, "C"] => play.commands[5] _ ReadCommand[t, stream]; Rope.Equal[token, "ball"] => play.ball _ ReadCommand[t, stream, TRUE]; ENDCASE => { IF play # NIL AND play.name # NIL THEN AddPlay[t, play]; play _ NEW[PlayRec _ []]; play.name _ token; token _ stream.GetTokenRope[IO.IDProc].token; IF Rope.Equal[token, "defensive"] THEN play.side _ defense; token _ stream.GetTokenRope[IO.IDProc].token; IF Rope.Equal[token, "play"] THEN play.setUp _ FALSE}; ENDLOOP; IF play # NIL AND play.name # NIL THEN AddPlay[t, play]; file.Close[]; MessageWindow.Append["done."]; }; ReadCommand: PROC[t: T, stream: IO.STREAM, ball: BOOLEAN_FALSE] RETURNS[Command] = { token: Rope.ROPE; action: Action _ block; target: Target _ [player[ball]]; myTeam: Team _ t.myTeam; WHILE ~stream.EndOf[] DO token _ stream.GetTokenRope[IO.IDProc].token; SELECT TRUE FROM Rope.Equal[token, "stop"] => RETURN[[stop, [null[ ]]]]; Rope.Equal[token, "block"] => action _ block; Rope.Equal[token, "guard"] => action _ block; Rope.Equal[token, "run"] => action _ run; Rope.Equal[token, "pass"] => IF ball THEN action _ pass; Rope.Equal[token, "kick"] => IF ball THEN action _ kick; Rope.Equal[token, "goal"] => target _ [goal[]]; Rope.Equal[token, "kick"] => IF ball THEN action _ kick; Rope.Equal[token, "ball"] => target _ [player[ball]]; Rope.Equal[token, "QB"] => target _ [player[IF myTeam = home THEN VQB ELSE HQB]]; Rope.Equal[token, "LE"] => target _ [player[IF myTeam = home THEN VLE ELSE HLE]]; Rope.Equal[token, "RE"] => target _ [player[IF myTeam = home THEN VRE ELSE HRE]]; Rope.Equal[token, "LG"] => target _ [player[IF myTeam = home THEN VLG ELSE HLG]]; Rope.Equal[token, "RG"] => target _ [player[IF myTeam = home THEN VRG ELSE HRG]]; Rope.Equal[token, "C"] => target _ [player[IF myTeam = home THEN VC ELSE HC]]; Rope.Equal[token, "location"] => {x, y: INTEGER; x _ stream.GetInt[]; y _ stream.GetInt[]; target _ [relative[x, y]]}; ENDCASE; ENDLOOP; RETURN[[action, target]]; }; SavePlay: PUBLIC PROC[t: T, side: Side, name: Rope.ROPE, playSetUp: BOOL] = { new: Play _ NEW[PlayRec _ []]; nextNew: Play _ IF playSetUp THEN t.current ELSE t.planned; new^ _ nextNew^; new.setUp _ playSetUp; new.side _ side; new.name _ name; AddPlay[t, new]; }; AddPlay: PROC[t: T, new: Play] = { OPEN t; line: Menus.MenuLine; entry: ViewerClasses.MenuEntry; IF new.name = NIL THEN new.name _ "Play"; FOR i: CARDINAL IN [0..6) DO IF new.commands[i].target.type # absolute THEN LOOP; new.commands[i].target _ Translate[t, new.commands[i].target, myTeam]; ENDLOOP; IF new.ball.target.type = absolute THEN new.ball.target _ Translate[t, new.ball.target, myTeam]; line _ IF new.setUp THEN 1 ELSE IF new.side = offense THEN 2 ELSE 3; entry _ FindEntry[viewer.menu, new.name, line]; IF entry # NIL THEN {entry.clientData _ new; RETURN}; entry _ Menus.CreateEntry[new.name, SetPlay, new]; Menus.AppendMenuEntry[viewer.menu, entry, line]; ViewerOps.SetMenu[viewer, viewer.menu]; }; FindEntry: PROC[menu: Menus.Menu, name: Rope.ROPE, line: Menus.MenuLine] RETURNS[entry: ViewerClasses.MenuEntry] = { FOR entry _ menu.lines[line], entry.link WHILE entry # NIL DO IF Rope.Equal[entry.name, name] THEN RETURN; ENDLOOP; }; Translate: PROC[t: T, target: Target, team: Team] RETURNS[Target] = { x, y: REAL _ 0; WITH targ: target SELECT FROM absolute => { y _ targ.y - fieldWidth/2; x _ (targ.x - t.game.scrimmage)*Direction[team, t.game.quarter]}; ENDCASE; RETURN[[relative[x, y]]]; }; SetPlay: Menus.ClickProc = TRUSTED { t: T _ FootballInternal.GetTFromViewer[parent]; BEGIN OPEN t; old: Play; new: Play _ NARROW[clientData, Play]; IF new = NIL THEN RETURN; IF control THEN { entry: ViewerClasses.MenuEntry; entry _ Menus.FindEntry[viewer.menu, new.name]; IF entry = NIL THEN RETURN; IF entry.clientData # new THEN RETURN; Menus.ReplaceMenuEntry[viewer.menu, entry, NIL]; ViewerOps.SetMenu[viewer, viewer.menu]; RETURN}; InputFocus.SetInputFocus[viewer]; old _ IF new.setUp OR game.state > setUp THEN current ELSE planned; old^ _ new^; IF game.state < option THEN FootballMaster.SetUp[myTeam]; IF old.setUp THEN RETURN; MessageWindow.Clear[]; IF (new.side = defense) AND (myTeam = game.offense) THEN { MessageWindow.Append["You have the ball. Select an offensive play.", TRUE]; MessageWindow.Blink[]}; IF (new.side = offense) AND (myTeam # game.offense) THEN { MessageWindow.Append["You don't have the ball. Select a defensive play.", TRUE]; MessageWindow.Blink[]}; END; -- OPEN t }; SetCommand: PUBLIC PROC[t: T, player: Position, command: Command, playSetUp: BOOL _ FALSE] = { BEGIN OPEN t; old: Play _ IF game.state > setUp OR playSetUp THEN current ELSE planned; IF player = ball AND old = planned THEN {old.ball _ command; RETURN}; IF player = ball THEN { player _ game.ballCarrier; IF command.target = [null[]] THEN IF old.ball.action # stop THEN command _ old.ball ELSE RETURN}; IF player = ball OR TeamOf[player] # myTeam THEN RETURN; IF command.action IN [pass..kick] AND player # game.ballCarrier THEN RETURN; IF command.action = kick THEN FOR i: CARDINAL IN [0..6) DO old.commands[i] _ [run, [player[ball]]]; ENDLOOP; old.commands[Index[player]] _ command; END; -- OPEN t }; SetCommandUp: PUBLIC PROC[t: T, player: Position, command: Command, playSetUp: BOOL _ TRUE] = { BEGIN OPEN t; old: Play; playSetUp _ TRUE; old _ IF game.state > setUp OR playSetUp THEN current ELSE planned; IF player = ball AND old = planned THEN {old.ball _ command; RETURN}; IF player = ball THEN { player _ game.ballCarrier; IF command.target = [null[]] THEN IF old.ball.action # stop THEN command _ old.ball ELSE RETURN}; IF player = ball OR TeamOf[player] # myTeam THEN RETURN; IF command.action IN [pass..kick] AND player # game.ballCarrier THEN RETURN; IF command.action = kick THEN FOR i: CARDINAL IN [0..6) DO old.commands[i] _ [run, [player[ball]]]; ENDLOOP; old.commands[Index[player]] _ command; END; -- OPEN t }; Index: PROC[player: Position] RETURNS[CARDINAL] = { IF TeamOf[player] = home THEN RETURN[LOOPHOLE[Add[player, -1]]] ELSE RETURN[LOOPHOLE[Add[player, -7]]]; }; Wait: ENTRY PROCEDURE[t: T, i: CARDINAL] = { DO IF i = 0 THEN EXIT ELSE i _ i - 1; WAIT t.playTimer; ENDLOOP; }; Control: PUBLIC PROC[t: T] = { OPEN t; player: Player; commands: Commands _ ALL[[stop, [null[]]]]; Process.SetTimeout[@playTimer, 1]; InitializePlays[t]; FootballMaster.KickOff[myTeam]; DO Wait[t, delay]; game^ _ FootballMaster.SetCommands[myTeam, commands]; IF game.state # state THEN SELECT game.state FROM offField => current.commands _ GetOffField[myTeam]; huddle => { current.commands _ GetHuddle[t, myTeam]; IF game.offense = myTeam THEN planned.commands _ ALL[[block, [player[all]]]] ELSE planned.commands _ ALL[[run, [player[ball]]]]}; option => current^ _ planned^; ENDCASE; FOR i: CARDINAL IN [0..6) DO player _ @game.player[Add[IF myTeam = home THEN HQB ELSE VQB, i]]; [commands[i].action, commands[i].target] _ GetCommand[t, player, game]; ENDLOOP; state _ game.state; carrier _ game.ballCarrier; IF viewer # NIL THEN ViewerOps.PaintViewer[viewer, client, FALSE, $Players]; ENDLOOP; }; GetCommand: PROC[t: T, player: Player, game: Game] RETURNS[action: Action, target: Target] = { x, y: REAL; OQB: Position; index: CARDINAL; OQB _ IF game.offense = home THEN HQB ELSE VQB; IF player.position = OQB AND game.state = option AND game.ballCarrier = none THEN RETURN[stop, [null[]]]; IF game.state # t.state AND game.state IN [pass..run] AND t.state NOT IN [pass..run] THEN FOR i: Position IN Players DO IF i = game.ballCarrier THEN LOOP; IF TeamOf[game.player[i].position] # game.possessor THEN SetCommand[t, i, [run, [player[ball]]]] ENDLOOP; IF game.state # t.state AND game.state = turnover THEN FOR i: Position IN Players DO IF i = game.ballCarrier THEN LOOP; IF TeamOf[game.player[i].position] = game.possessor THEN SetCommand[t, i, [block, [player[all]]]] ELSE SetCommand[t, i, [run, [player[ball]]]]; ENDLOOP; IF game.state # t.state AND game.state = liveBall THEN FOR i: Position IN Players DO SetCommand[t, i, [run, [player[ball]]]] ENDLOOP; IF game.ballCarrier # t.carrier AND player.position = game.ballCarrier AND game.state # option THEN SetCommand[t, player.position, [run, [goal[]]]]; index _ Index[player.position]; action _ t.current.commands[index].action; target _ t.current.commands[index].target; IF t.selected # none AND player.position = t.selected THEN RETURN; WITH targ: target SELECT FROM relative => { y _ targ.y + fieldWidth/2; x _ game.scrimmage + targ.x*Direction[TeamOf[player.position], game.quarter]}; absolute => {x _ targ.x; y _ targ.y}; ENDCASE => RETURN; IF game.state < option AND t.myTeam # game.offense AND t.current.commands[Index[player.position]].action # stop THEN WITH targ: t.planned.commands[index].target SELECT FROM player => { dy: REAL; p2: Player = @game.player[targ.position]; IF ~CenterReady[t] OR targ.position = ball THEN RETURN; IF ABS[player.x - game.scrimmage] > 3.5 THEN RETURN; dy _ ABS[player.y - p2.y]; IF dy < 3.5 AND ABS[player.dy] < .05 THEN RETURN; -- don't move IF dy < 10 AND p2.dy > .5 AND p2.y < player.y THEN RETURN; -- moving toward me IF dy < 10 AND p2.dy < -.5 AND p2.y > player.y THEN RETURN; -- moving toward me IF Blocked[t, player, p2.y] THEN IF ABS[player.x - game.scrimmage] < 2.9 THEN target _ [relative[-3, player.y - fieldWidth/2]] ELSE target _ [relative[-3, p2.y - fieldWidth/2]] ELSE target _ [relative[-1, p2.y - fieldWidth/2]]; t.current.commands[Index[player.position]] _ [run, target]}; ENDCASE; IF action # run OR game.state < option THEN RETURN; IF ABS[player.x - x] < .5 AND ABS[player.y - y] < .5 THEN SELECT TRUE FROM player.position = game.ballCarrier AND player.position = OQB => NULL; player.position = game.ballCarrier => SetCommand[t, player.position, [run, [goal[]]]]; TeamOf[player.position] # game.possessor => SetCommand[t, player.position, [run, [player[ball]]]]; game.state = run => SetCommand[t, player.position, [block, [player[ball]]]]; game.state = pass => SetCommand[t, player.position, [run, [player[ball]]]]; ENDCASE; RETURN[action, [absolute[x, y]]]; }; Blocked: PROC[t: T, player: Player, p2y: REAL] RETURNS [BOOLEAN] = INLINE { FOR i: Position IN Players DO IF i = player.position THEN LOOP; IF TeamOf[i] # TeamOf[player.position] THEN LOOP; IF ABS[t.game.player[i].x - t.game.scrimmage] > 1.5 THEN LOOP; IF player.y+1 < t.game.player[i].y AND p2y+1 < t.game.player[i].y THEN LOOP; IF player.y > t.game.player[i].y+1 AND p2y > t.game.player[i].y+1 THEN LOOP; RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; CenterReady: PROC[t: T] RETURNS[BOOLEAN] = INLINE { center: Position = IF t.game.offense = home THEN HC ELSE VC; RETURN[ABS[t.game.player[center].x - t.game.scrimmage] < 2]; }; Convert: PROC[pos: Position] RETURNS[Position] = INLINE { IF pos IN HomeTeam THEN RETURN[Add[pos, 6]]; IF pos IN VisitorsTeam THEN RETURN[Add[pos, -6]]; RETURN[pos]; }; Add: PROCEDURE[p: Position, i: INTEGER] RETURNS[Position] = INLINE { RETURN[LOOPHOLE[LOOPHOLE[p, INTEGER]+i]]; }; OHuddle: Commands = [ [run, [relative[-18, 0]]], [run, [relative[-16, -4]]], [run, [relative[-16, 4]]], [run, [relative[-14, -4]]], [run, [relative[-14, 4]]], [run, [relative[-12, 0]]]]; DHuddle: Commands = [ [run, [relative[-18, 0]]], [run, [relative[-16, -4]]], [run, [relative[-16, 4]]], [run, [relative[-14, -4]]], [run, [relative[-14, 4]]], [run, [relative[-14, 0]]]]; LOEndZoneHuddle: Commands = [ [run, [absolute[-8, 26]]], [run, [absolute[-6, 22]]], [run, [absolute[-6, 30]]], [run, [absolute[-4, 22]]], [run, [absolute[-4, 30]]], [run, [absolute[-2, 26]]]]; LDEndZoneHuddle: Commands = [ [run, [absolute[-8, 26]]], [run, [absolute[-6, 22]]], [run, [absolute[-6, 30]]], [run, [absolute[-4, 22]]], [run, [absolute[-4, 30]]], [run, [absolute[-4, 26]]]]; ROEndZoneHuddle: Commands = [ [run, [absolute[108, 26]]], [run, [absolute[106, 22]]], [run, [absolute[106, 30]]], [run, [absolute[104, 22]]], [run, [absolute[104, 30]]], [run, [absolute[102, 26]]]]; RDEndZoneHuddle: Commands = [ [run, [absolute[108, 26]]], [run, [absolute[106, 22]]], [run, [absolute[106, 30]]], [run, [absolute[104, 22]]], [run, [absolute[104, 30]]], [run, [absolute[104, 26]]]]; offField1: Commands = [ [run, [absolute[23, 55]]], [run, [absolute[26, 55]]], [run, [absolute[29, 55]]], [run, [absolute[32, 55]]], [run, [absolute[35, 55]]], [run, [absolute[38, 55]]]]; offField2: Commands = [ [run, [absolute[77, -5]]], [run, [absolute[74, -5]]], [run, [absolute[71, -5]]], [run, [absolute[68, -5]]], [run, [absolute[65, -5]]], [run, [absolute[62, -5]]]]; GetHuddle: PROC[t: T, team: Team] RETURNS[commands: Commands] = { game: Game _ t.game; SELECT TRUE FROM Direction[team, game.quarter] = 1 AND game.scrimmage < 10 => RETURN[IF team = game.offense THEN LOEndZoneHuddle ELSE LDEndZoneHuddle]; Direction[team, game.quarter] =-1 AND game.scrimmage > 90 => RETURN[IF team = game.offense THEN ROEndZoneHuddle ELSE RDEndZoneHuddle]; ENDCASE => RETURN[IF team = game.offense THEN OHuddle ELSE DHuddle]; }; GetOffField: PROC[team: Team] RETURNS[Commands] = INLINE { RETURN[IF team = home THEN offField1 ELSE offField2]; }; InitializePlays: PROC[t:T] = { OPEN t; current.commands _ [ [run, [relative[-3, 0]]], [run, [relative[-1, -8]]], [run, [relative[-1, 8]]], [run, [relative[-1, -4]]], [run, [relative[-1, 4]]], [run, [relative[-1, 0]]]]; SavePlay[t, offense, "5-1", TRUE]; current.commands _ [ [run, [relative[-1, -2]]], [run, [relative[-6, -2]]], [run, [relative[-6, 2]]], [run, [relative[-1, -6]]], [run, [relative[-1, 6]]], [run, [relative[-1, 2]]]]; SavePlay[t, offense, "4-2", TRUE]; current.commands _ [ [run, [relative[-45, 0]]], [run, [relative[-1, -8]]], [run, [relative[-1, 8]]], [run, [relative[-1, -4]]], [run, [relative[-1, 4]]], [run, [relative[-1, 0]]]]; SavePlay[t, offense, "punt-reception", TRUE]; planned.commands _ [ [run, [relative[5, -4]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]]]; SavePlay[t, offense, "UpTheMiddle", FALSE]; planned.commands _ [ [run, [relative[-10, 3]]], [block, [player[all]]], [run, [relative[10, 10]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]]]; planned.ball _ [pass, [relative[10, 10]]]; SavePlay[t, offense, "ShortPassTop", FALSE]; planned.commands _ [ [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]; SavePlay[t, defense, "Rush", FALSE]; IF myTeam = home THEN planned.commands _ [ [run, [player[ball]]], [run, [player[VLE]]], [run, [player[VRE]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]; IF myTeam = visitors THEN planned.commands _ [ [run, [player[ball]]], [run, [player[HLE]]], [run, [player[HRE]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]; SavePlay[t, defense, "GuardEnds", FALSE]; IF myTeam = home THEN planned.commands _ [ [run, [player[VQB]]], [run, [player[VLE]]], [run, [player[VRE]]], [run, [player[VLG]]], [run, [player[VRG]]], [run, [player[VC]]]]; IF myTeam = visitors THEN planned.commands _ [ [run, [player[HQB]]], [run, [player[HLE]]], [run, [player[HRE]]], [run, [player[HLG]]], [run, [player[HRG]]], [run, [player[HC]]]]; SavePlay[t, defense, "ManToMan", FALSE]; planned.commands _ [ [run, [player[ball]]], [block, [relative[-10, -15]]], [block, [relative[-10, 15]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]; SavePlay[t, defense, "Zone", FALSE]; planned.commands _ [ [stop, [null[]]], [block, [player[ball]]], [block, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]; SavePlay[t, defense, "punt-reception", FALSE]; current.commands _ GetOffField[myTeam]; }; } . . . ΈFootballPlays.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Maxwell, March 15, 1983 8:21 am Spreitzer, May 1, 1984 11:00:35 pm PDT Rumph, May 15, 1984 12:08:07 pm PDT Russ Atkinson (RRA) July 1, 1987 11:45:30 am PDT Swinehar, December 5, 1990 9:40 am PST Doug Terry, December 30, 1992 10:02 am PST RPC USING [CallFailed], ,RPC ****************************************************************** playBooks ****************************************************************** ****************************************************************** preplanned plays ****************************************************************** ****************************************************************** interactive user commands ****************************************************************** set a default pass should we use the default pass/kick? is this legal? move all of the players down the field set the new command set a default pass should we use the default pass/kick? is this legal? move all of the players down the field set the new command ****************************************************************** interface with control module ****************************************************************** ENABLE RPC.CallFailed => CHECKED {CONTINUE}; QB shouldn't move until the ball gets to him check for interesting state changes if the ball is caught anytime but the hike, the receiver should run towards the goal translate location relative to scrimmage line follow split ends have we reached our target? ****************************************************************** simple plays ****************************************************************** offensive plays defensive plays Κp– "cedar" style˜codešœ™Kšœ Οmœ1™Kšžœ!žœžœžœ˜LKšžœ!žœžœžœ˜LKšžœžœ˜Kšžœ˜—Kšžœžœ˜Kšœ˜K˜—š Ÿ œžœžœžœžœ˜3Kš œžœžœžœžœžœ˜