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: 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 . . .