<> <> <> FootballMaster: DEFINITIONS = BEGIN SetCommands: PROC[team: Team, c: Commands] RETURNS[GameRec]; KickOff: PROCEDURE[team: Team]; SetUp: PROCEDURE[team: Team]; Hike: PROCEDURE[team: Team]; TimeOut: PROCEDURE[team: Team]; PenaltyResponse: PROCEDURE[team: Team, accepted: BOOLEAN]; DisableDelayOfGame: PROCEDURE; Game: TYPE = REF GameRec; GameRec: TYPE = RECORD[ quarter: Quarter _ 1, clock: INTEGER _ 15*60, clockStopped: BOOLEAN _ FALSE, score: ARRAY Team OF INTEGER _ [0, 0], timeouts: ARRAY Team OF INTEGER _ [4, 4], penalties: ARRAY Team OF Penalty _ [none, none], penaltyState: PenaltyState _ none, down: Down _ 1, offense: Team _ home, possessor: Team _ home, scrimmage: REAL _ 20, firstDownMarker: REAL _ 30, ballCarrier: Position _ ball, ballCatchable: Target _ [null[]], -- place where the ball first becomes catchable ballTarget: Target _ [null[]], -- place where the ball hits the ground ballRange: REAL _ 0, -- range over which ball is catchable pass: BOOLEAN _ FALSE, -- is this a pass? (as opposed to a hike or kick) lateral: BOOLEAN _ FALSE, -- is this a lateral pass? state: State _ offField, player: ARRAY Position OF PlayerRec _ ALL[[]]]; Player: TYPE = LONG POINTER TO PlayerRec; PlayerRec: TYPE = RECORD[ x, y: REAL _ 0, dx, dy: REAL _ 0, -- used to simulate inertia position: Position _ none, blocking: Position _ none]; State: TYPE = {offField, huddle, setUp, option, pass, catchable, liveBall, run, turnover}; Quarter: TYPE = [1..5]; Down: TYPE = [1..5]; Team: TYPE = {home, visitors}; Side: TYPE = {offense, defense}; Position: TYPE = {ball, HQB, HLE, HRE, HLG, HRG, HC, VQB, VLE, VRE, VLG, VRG, VC}; none, all, self: Position = ball; -- a convenience Players: TYPE = Position[HQB..VC]; HomeTeam: TYPE = Position[HQB..HC]; VisitorsTeam: TYPE = Position[VQB..VC]; Penalty: TYPE = {none, offSides, formation, motion, interference, forwardPass, grounding, delayOfGame}; PenaltyState: TYPE = {none, asking, accepted, declined, canceled}; Commands: TYPE = ARRAY [0..6) OF Command; Command: TYPE = RECORD[action: Action, target: Target]; Action: TYPE = {pass, kick, run, block, stop}; -- defensive 'block' is guarding Target: TYPE = RECORD[t: SELECT type: * FROM null, goal => NULL, player => [position: Position], -- includes player[ball] relative => [x, y: REAL], -- relative to scrimmage line absolute => [x, y: REAL], -- fixed position ENDCASE]; fieldWidth: INTEGER = 160/3; -- regulation size TeamOf: PROC[pos: Position] RETURNS[team: Team] = INLINE {RETURN[IF pos IN [VQB..VC] THEN visitors ELSE home]}; Opponent: PROC[team: Team] RETURNS[Team] = INLINE {RETURN[IF team = home THEN visitors ELSE home]}; Direction: PROCEDURE[team: Team, quarter: Quarter] RETURNS[INTEGER] = INLINE {RETURN[IF ((quarter MOD 2 = 1) = (team = home)) THEN 1 ELSE -1]}; CrossLine: PROCEDURE[x, line: REAL, team: Team, quarter: Quarter] RETURNS[BOOLEAN] = INLINE {IF Direction[team, quarter] = 1 THEN RETURN[x > line] ELSE RETURN[x < line]}; EndZone: PROC[scrimmage: REAL] RETURNS[BOOLEAN] = INLINE {RETURN[scrimmage < 0 OR scrimmage > 100]}; Goal: PROCEDURE[team: Team, quarter: Quarter, back: BOOLEAN _ FALSE] RETURNS[goalLine: INTEGER] = INLINE BEGIN direction: INTEGER _ Direction[team, quarter]; goalLine _ IF direction = 1 THEN 0 ELSE 100; IF back THEN goalLine _ goalLine - direction*10; RETURN[goalLine]; END; StupidFuckingWarnings: SIGNAL [itsGottaHaveAGoddamName: ATOM]; END . . .