FootballMaster.mesa
Last Edited by: Maxwell, February 9, 1983 10:14 am
Last Edited by: Spreitzer, May 1, 1984 9:48:33 pm PDT
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: BOOLEANFALSE,
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: BOOLEANFALSE, -- is this a pass? (as opposed to a hike or kick)
lateral: BOOLEANFALSE, -- 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: BOOLEANFALSE]
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 . . .