DIRECTORY Commander USING [CommandProc, Handle, Register], CommanderOps USING [NextArgument], FS USING [StreamOpen, Error], IO USING [Close, EndOf, EndOfStream, GetInt, GetLineRope, GetTokenRope, IDProc, rope, RIS, STREAM], Process USING [Detach, Pause, MsecToTicks, SecondsToTicks], Random USING [RandomStream, Create, ChooseInt], Rope USING [Equal, ROPE], SimpleFeedback, FootballInternal, FootballMaster; FootballHero: CEDAR PROGRAM IMPORTS Commander, CommanderOps, FootballInternal, FootballMaster, FS, IO, Rope, Process, Random, SimpleFeedback = { OPEN FootballMaster, FootballInternal; QBStates: TYPE = {CallingPlay, CallingSignals, WaitingForSnap, BackToPass, BackToKick, ExecutingPlay}; delay: CARDINAL _ 25; rs: Random.RandomStream; teamInfo: ARRAY Team OF T _ ALL[NIL]; defaultPlaybookFile: Rope.ROPE _ "./FootballHero.plays"; PlayType: TYPE = {setup, play}; Playbook: TYPE = ARRAY Side OF ARRAY PlayType OF RECORD[ num: INT _ 0, plays: ARRAY [0..100] OF Play ]; PuntingPlaybook: TYPE = ARRAY Side OF ARRAY PlayType OF Play; puntingPlaysInit: BOOLEAN _ FALSE; puntingPlays: PuntingPlaybook; teamPlays: ARRAY Team OF Playbook; teamPlaybookFile: ARRAY Team OF ROPE; ReportState: PROC [t: T, msg: ROPE] RETURNS [] ~ { state: ROPE _ SELECT t.game.state FROM offField => "offField", huddle => "huddle", setUp => "setUp", option => "option", pass => "pass", catchable => "catchable", liveBall => "liveBall", run => "run", turnover => "turnover", ENDCASE => "other"; SimpleFeedback.PutF[$FBHero, $begin, NIL, "team=%s", IO.rope[IF t.myTeam = home THEN "home" ELSE "visitors"]]; SimpleFeedback.PutF[$FBHero, $middle, NIL, ",state=%s: ", IO.rope[state]]; SimpleFeedback.Append[$FBHero, $end, NIL, msg]; }; AutoControl: PROC [myTeam: Team, playbookFile: ROPE] RETURNS [] ~ TRUSTED { t: T _ teamInfo[myTeam]; game: Game _ t.game; qbstate: QBStates _ CallingPlay; myQB: Position _ IF myTeam = home THEN HQB ELSE VQB; formation: Play; play: Play; SetUpPlaybook[myTeam, playbookFile]; DO Process.Pause[Process.MsecToTicks[delay]]; IF teamInfo[myTeam] = NIL THEN EXIT; SELECT qbstate FROM CallingPlay => { [formation, play] _ CallPlay[myTeam, game]; Process.Pause[Process.SecondsToTicks[5]]; -- time in huddle FOR i: CARDINAL IN [0..6) DO FootballInternal.SetCommandUp[t: t, player: Player[myTeam, i], command: formation.commands[i], playSetUp: TRUE]; ENDLOOP; FootballMaster.SetUp[myTeam]; Process.Pause[Process.SecondsToTicks[5]]; -- time to get to line of scrimage FOR i: CARDINAL IN [0..6) DO FootballInternal.SetCommand[t: t, player: Player[myTeam, i], command: play.commands[i], playSetUp: FALSE]; ENDLOOP; qbstate _ IF game.offense = myTeam THEN CallingSignals ELSE WaitingForSnap; Process.Pause[Process.SecondsToTicks[2]]; -- time to call signals }; CallingSignals => { FootballMaster.Hike[myTeam]; Process.Pause[5]; -- wait long enough to see if ball was actually snapped IF game.state > setUp THEN qbstate _ SELECT play.ball.action FROM pass => BackToPass, kick => BackToKick, ENDCASE => ExecutingPlay; }; WaitingForSnap => { IF game.state > setUp THEN qbstate _ ExecutingPlay; }; BackToPass => { IF game.ballCarrier = myQB AND ReceiverInArea[myTeam, game, play.ball.target, 5] THEN { FootballInternal.SetCommand[t, ball, play.ball]; qbstate _ ExecutingPlay; }; IF game.state < option THEN -- play must be over qbstate _ CallingPlay; }; BackToKick => { IF game.ballCarrier = myQB THEN { FootballInternal.SetCommand[t, ball, [kick, [goal[]]]]; qbstate _ ExecutingPlay; }; IF game.state < option THEN -- play must be over qbstate _ CallingPlay; }; ExecutingPlay => { IF game.state < option THEN -- play must be over qbstate _ CallingPlay; }; ENDCASE; IF game.penaltyState = asking AND game.penalties[Opponent[myTeam]] # none THEN { FootballMaster.PenaltyResponse[myTeam, TRUE]; qbstate _ CallingPlay; }; ENDLOOP; }; SetUpPuntingPlaybook: PROC [] RETURNS [] ~ { IF puntingPlaysInit = TRUE THEN RETURN; puntingPlays[offense][setup] _ NEW[PlayRec]; puntingPlays[defense][setup] _ NEW[PlayRec]; puntingPlays[offense][play] _ NEW[PlayRec]; puntingPlays[defense][play] _ NEW[PlayRec]; puntingPlays[offense][setup]^ _ [name: "Punt-formation", 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]]]]]; puntingPlays[defense][setup]^ _ [name: "Punt-reception", 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]]]]]; puntingPlays[offense][play]^ _ [name: "Punt", ball: [kick, [goal[]]], commands: [ [run, [relative[-10, 3]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]]]]; puntingPlays[defense][play]^ _ [name: "Punt-return", commands: [ [stop, [null[]]], [block, [player[ball]]], [block, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]]; puntingPlaysInit _ TRUE; }; ManualSetUpPlaybook: PROC [myTeam: Team] RETURNS [] ~ { SetUpPuntingPlaybook[]; teamPlaybookFile[myTeam] _ "manual"; teamPlays[myTeam][offense][setup].plays[0] _ NEW[PlayRec]; teamPlays[myTeam][defense][setup].plays[0] _ NEW[PlayRec]; teamPlays[myTeam][offense][play].plays[0] _ NEW[PlayRec]; teamPlays[myTeam][offense][play].plays[1] _ NEW[PlayRec]; teamPlays[myTeam][defense][play].plays[0] _ NEW[PlayRec]; teamPlays[myTeam][defense][play].plays[1] _ NEW[PlayRec]; teamPlays[myTeam][defense][play].plays[2] _ NEW[PlayRec]; teamPlays[myTeam][defense][play].plays[3] _ NEW[PlayRec]; teamPlays[myTeam][offense][setup].plays[0]^ _ [name: "5-1", 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]]]]]; teamPlays[myTeam][offense][setup].num _ 1; teamPlays[myTeam][defense][setup].plays[0]^ _ [name: "4-2", 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]]]]]; teamPlays[myTeam][defense][setup].num _ 1; teamPlays[myTeam][offense][play].plays[0]^ _ [name: "UpTheMiddle", commands: [ [run, [relative[5, -4]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]]]]; teamPlays[myTeam][offense][play].plays[1]^ _ [name: "ShortPassTop", ball: [pass, [relative[10, 10]]], commands: [ [run, [relative[-10, 3]]], [block, [player[all]]], [run, [relative[10, 10]]], [block, [player[all]]], [block, [player[all]]], [block, [player[all]]]]]; teamPlays[myTeam][offense][play].num _ 2; teamPlays[myTeam][defense][play].plays[0]^ _ [name: "Rush", commands: [ [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]]; teamPlays[myTeam][defense][play].plays[1]^ _ [name: "GuardEnds", commands: IF myTeam = home THEN [ [run, [player[ball]]], [run, [player[VLE]]], [run, [player[VRE]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]] ELSE [ [run, [player[ball]]], [run, [player[HLE]]], [run, [player[HRE]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]]; teamPlays[myTeam][defense][play].plays[2]^ _ [name: "ManToMan", commands: IF myTeam = home THEN [ [run, [player[VQB]]], [run, [player[VLE]]], [run, [player[VRE]]], [run, [player[VLG]]], [run, [player[VRG]]], [run, [player[VC]]]] ELSE [ [run, [player[HQB]]], [run, [player[HLE]]], [run, [player[HRE]]], [run, [player[HLG]]], [run, [player[HRG]]], [run, [player[HC]]]]]; teamPlays[myTeam][defense][play].plays[3]^ _ [name: "Zone", commands: [ [run, [player[ball]]], [block, [relative[-10, -15]]], [block, [relative[-10, 15]]], [run, [player[ball]]], [run, [player[ball]]], [run, [player[ball]]]]]; teamPlays[myTeam][defense][play].num _ 4; }; SetUpPlaybook: PROC [myTeam: Team, playbookFile: ROPE] RETURNS [] ~ { -- stolen from FootballPlays.mesa ENABLE FS.Error => {ManualSetUpPlaybook[myTeam]; CONTINUE}; play: Play; line, token: Rope.ROPE; stream, file: IO.STREAM; IF playbookFile = NIL THEN playbookFile _ defaultPlaybookFile; teamPlaybookFile[myTeam] _ playbookFile; SetUpPuntingPlaybook[]; file _ FS.StreamOpen[playbookFile]; 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[myTeam, stream]; Rope.Equal[token, "LE"] => play.commands[1] _ ReadCommand[myTeam, stream]; Rope.Equal[token, "RE"] => play.commands[2] _ ReadCommand[myTeam, stream]; Rope.Equal[token, "LG"] => play.commands[3] _ ReadCommand[myTeam, stream]; Rope.Equal[token, "RG"] => play.commands[4] _ ReadCommand[myTeam, stream]; Rope.Equal[token, "C"] => play.commands[5] _ ReadCommand[myTeam, stream]; Rope.Equal[token, "ball"] => play.ball _ ReadCommand[myTeam, stream, TRUE]; ENDCASE => { IF play # NIL AND play.name # NIL THEN AddPlay[myTeam, 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[myTeam, play]; file.Close[]; }; ReadCommand: PROC[myTeam: Team, stream: IO.STREAM, ball: BOOLEAN_FALSE] RETURNS[Command] = TRUSTED { -- stolen from FootballPlays.mesa token: Rope.ROPE; action: Action _ block; target: Target _ [player[ball]]; 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]]; }; AddPlay: PROC[myTeam: Team, new: Play] = { pt: PlayType = IF new.setUp THEN setup ELSE play; teamPlays[myTeam][new.side][pt].plays[teamPlays[myTeam][new.side][pt].num] _ new; teamPlays[myTeam][new.side][pt].num _ teamPlays[myTeam][new.side][pt].num + 1; }; CallPlay: PROC [myTeam: Team, game: Game] RETURNS [formation, play: Play] ~ { myside: Side = IF game.offense = myTeam THEN offense ELSE defense; IF game.down = 4 THEN { formation _ puntingPlays[myside][setup]; play _ puntingPlays[myside][play]; } ELSE { formation _ teamPlays[myTeam][myside][setup].plays[Random.ChooseInt[rs: rs, max: teamPlays[myTeam][myside][setup].num-1]]; play _ teamPlays[myTeam][myside][play].plays[Random.ChooseInt[rs: rs, max: teamPlays[myTeam][myside][play].num-1]]; }; }; ReceiverInArea: PROC [myTeam: Team, game: Game, area: Target, delta: REAL _ 1] RETURNS [BOOL] ~ { x, y: REAL; [x, y] _ GetTarget[myTeam, game, area]; FOR i: CARDINAL IN [0..6) DO IF ABS[y - game.player[Player[myTeam, i]].y] < delta AND ABS[x - game.player[Player[myTeam, i]].x] < delta THEN RETURN [TRUE]; ENDLOOP; RETURN [FALSE]; }; GetTarget: PROC [myTeam: Team, game: Game, target: Target] RETURNS [tx, ty: REAL] ~ { goal: INTEGER; TRUSTED { goal _ Goal[Opponent[myTeam], game.quarter, TRUE]; }; WITH t: target SELECT FROM goal => RETURN [goal, fieldWidth/2]; player => RETURN[game.player[t.position].x, game.player[t.position].y]; relative => RETURN [game.scrimmage + (IF goal > 50 THEN t.x ELSE -t.x), fieldWidth/2 + t.y]; absolute => RETURN [t.x, t.y]; ENDCASE => ERROR; }; Player: PROC [myTeam: Team, i: INTEGER] RETURNS [Position] ~ TRUSTED INLINE { myQB: Position _ IF myTeam = home THEN HQB ELSE VQB; RETURN[LOOPHOLE[LOOPHOLE[myQB, INTEGER]+i]]; }; StartStop: Commander.CommandProc = { file: Rope.ROPE; myTeam: Team; IF CommanderOps.NextArgument[cmd].Equal["visitors", FALSE] THEN myTeam _ visitors ELSE myTeam _ home; IF CommanderOps.NextArgument[cmd].Equal["stop", FALSE] THEN { IF teamInfo[myTeam] = NIL THEN RETURN[msg: "Football hero not running"]; teamInfo[myTeam] _ NIL; RETURN[msg: "Football hero stopped"]; }; IF teamInfo[myTeam] # NIL THEN RETURN[msg: "Football hero already running"]; file _ CommanderOps.NextArgument[cmd]; IF rs = NIL THEN rs _ Random.Create[seed: -1]; TRUSTED { teamInfo[myTeam] _ FootballInternal.GetTFromTeam[myTeam]; IF teamInfo[myTeam] = NIL THEN RETURN[msg: "Football team not currently on the field"]; Process.Detach[FORK AutoControl[myTeam, file]]; }; }; Commander.Register[key: "FootballHero", proc: StartStop, doc: "Computerized control for football arcade game.\n usage: FootballHero {home|visitors} {start|stop} [playbook]"]; } . . . xFootballHero.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Doug Terry, December 30, 1992 11:38 am PST A computer controlled football player. Global data Side: TYPE = {offense, defense}; -- from FootballMaster Main control loop ReportState[t, "Calling play..."]; set formation ReportState[t, "Setting formation..."]; FootballInternal.SetCommand[t: t, player: Player[myTeam, i], command: formation.commands[i], playSetUp: TRUE]; ReportState[t, "Lining up..."]; set play ReportState[t, "Setting play..."]; ReportState[t, "Calling signals or waiting for snap..."]; Process.Pause[20]; -- give receiver a few more seconds to get to spot Play calling this should really read a playbook file offensive setups defensive setups offensive plays defensive plays Registrations and command procs [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] ส D– "cedar" style˜codešœ™Kšœ ฯmœ1™