The well known game "Snake" in ADA with a safe approach, on Console (Unix) with additional features
Build with gprbuild
:
gprbuild -d -PSnake/snake.gpr Snake/src/main.adb
Run:
./Snake/obj/main
- Set the size
- Menu
- Change the controls
- Set color on/off
- Pause/Play
Controls in the menu are display and can't be changed.
var ctxt GameContext.Context = Initialisation // init the programme
var field InGame.Field = InGame.CreatField(&ctxt)
var snake InGame.Snake = InGame.CreatSnake(&ctxt)
task Keybording (Start) {
var input char
wait Start
loop {
get_immediat(&input)
switch input {
case ctxt.Config.Keymapped(Up): snake.ChangeDir(Up)
case ctxt.Config.Keymapped(Down): snake.ChangeDir(Down)
case ctxt.Config.Keymapped(Left): snake.ChangeDir(Left)
case ctxt.Config.Keymapped(Right): snake.ChangeDir(Right)
case ctxt.Config.Keymapped(Pause): ctxt.Game.Pause
case ctxt.Config.Keymapped(ExitGame): ctxt.Game.Stop(Stoped)
case others: NOTHING
}
}
}
main {
Menu(ctxt)
field.Paint
emit Keybording.Start
loop {
while ctxt.Game.Pausing {
field.HidePt
field.NextPt
}
break if !ctxt.Game.Running
break if !field.Check(snake)
field.DisplayPt
snake.PrintScore
snake.Move
delay 0.15 second
}
ctxt.PrintEndGame
}
- Load your own field with a special file format
- Save the current state of your game to come back latter
- Multiple levels
- Different zoom
- Build your field
- Different snake speed
type PosTerm & SizeTerm
Used to navigate on the console
Constraint: range 0 .. 100
const StartTerm : PosTerm
use to make an offset too print on the console, to be sure we don't Print at 0, because it wouldn't be visible.
type Position : record
public record that represent a position with coordinates x, y.
x :
PosTerm
- x coordinate.y :
PosTerm
- y coordinate.
type VectorPos --> Vectors(Natural, Position).Vector
A dynamic size array of
Position
from generic package Ada.Container.Vectors.
type RandomPos --> Discrete_Random(PosTerm).Generator
A random generator of
Position
from generic package Ada.Numerics.Discrete_Random.
type ColorName
enumeration of color for the console
procedure Print_at
args:
- str :
String
- The things to print- from :
Position
- The position to print or x, y :PosTerm
- The coordinatesPrint a message to the position/coordiate indicates. It interfaces a C function to handle the console navigation correctly.
procedure Print
A call to Ada.Text_io.Put
procedure MoveTo
args:
- x, y :
PosTerm
- The coordinate to move the cursor at.Move the terminal cursor to the coordiante indicates. It interfaces a C function to handle the console navigation correctly.
procedure SetColor
args:
- c :
ColorName
- The color to setSet the color in the console. It interfaces a C function to handle the console correctly.
procedure EraseConsole
Erase the console. It interfaces a C function to handle the console correctly.
type Key
enumeration of the possible Key to interacte in the game.
type KeyMap
Array of
Character
onKey
rangeThat type is use to binds a
Character
to eachKey
.
type ZoomIndice
Represent the zoom possible, from 1 to 3.
WARNING: zoom management is not implemented in the game
type Level
Represent the different level possible. LvCustom is supposed to be for letting the user give a file with a special format.
WARNING: level management is not implemented in the game
type GameStopedInfo
Represent the state of the game, and the reason of why the game is stoped if not Processing.
procedure displayMenu
display the menu
type Configuration tagged record
Holds the configuration of the game
(
in
) function Colorreturn
Boolean
Say if the color is set of not
(
in
) function Zoomreturn
ZoomIndice
Allows to know wich zoom is set
WARNING zoom management is not implemented in the game
(
in
) function KeyMappedargs:
k :
Key
return
Character
Get the character that has been mapped to the key "k".
procedure SetUpConfig
args:
ctxt :
in out Context
- The context that owns the config to set upSet up the configuration. Display a configuration panel for the user to change as he wants.
type GameInfo tagged record
Holds information about the game, and allows to interact with it.
(
in
) function Runningreturn
Boolean
Say if the game is running or not.
(
in
) function Pausingreturn
Boolean
Pre =>
.Running
Say if the game is in pause or not.
(
in out
) procedure StopGameargs:
reason :
GameStopedInfo
- Why do we stop the game.Pre =>
.Running
Post =>
not .Running
Stop the game through different reasons.
(
in out
) procedure PausePre =>
.Running
Post =>
.Running and not .Pausing
Pause the game
procedure SetUpGameInfo
args:
ctxt :
in out Context
- The context that owns the GameInfo to set upSet up the Game's information right befor lunching the game. Display a configuration panel for the user to select the level he wants.
WARNING: level management is not implemented in the game
? type Context tagged record
(
in
) function MaxWidthreturn
SizeTerm
Give the max width to display on the console, specify by the user.
(
in
) function MaxHeightreturn
SizeTerm
Give the max height to display on the console, specify by the user.
(
in
) function Configreturn
Configuration'Class
- 'Class to make the dispatching possibleGive the configuration settings.
(
in out
) function Gamereturn
access GameInfo'Class
- The game information may change durring the game.Post =>
.Game /= null
(
in
) procedure EndGameargs:
score :
Integer
- The score at the end of the gamePre =>
not .Game.Running
Display the end of the game with the score and the reason of the lost.
function CreatContext
args:
width, height :
SizeTerm
- the dimention of the max size to set for the contextreturn
Context
Post =>
CreatContext'Result.Game.Running
##InGame Pkg: Field Pkg and Snake Pkg
package.type Direction.Dir
A constraint integer from -2 to 2
with
a value/= 0
.const Up = -1
const Down = 1
const Left = -2
const Right = 2
The logic is that it is not possible to make
Up + Down
norLeft + Right
as 0 isn't a value; And in the snake it is not possible to switch from on direction to its opposite.
function NextPosFrom
args:
dir :
in Direction.Dir
pos :
Position
return
Position
Post
pos /= NextPosFrom'Result
Gives the next position regarding a direction.
type Snake tagged record
It represent the snake.
(
in
) procedure DisplayPre
.Ghost.GameRunning
Display the snake.
(
in out
) procedure MovePre
.Ghost.GameRunning
Post
.Pos'Old /= .Pos and .Pos = NextPosFrom(.Ghost.Dir, .Pos)
Move the snake to the last direction set.
(
in out
) procedure Posargs:
p :
Position
Post
.Pos = p
Setter of the position of the snake.
(
in
) function Posreturn
Position
Getter of the position of the snake.
(
in out
) procedure ChangeDirargs:
dir :
in Direction.Dir
Post
Integer(.Ghost.Dir) = Integer(dir)
Change the direction of the snake.
(
in out
) procedure AddPointPost
.Ghost.GameRunning and .Score = .'Old.Score + 1
Add a point to the snake, that make its length aka its score bigger.
(
in
) function Scorereturn
Integer
Return the current score of the snake and its length.
function Creat
args:
ctxt :
in out GameContext.Context
return
Snake
Pre
ctxt.Game.Running and ctxt'Unchecked_Access /= null
Creat the snake according to the game context.
type FieldElem
Enumeration used to represent the kind of the field.
function Char
args:
elem :
in FieldElem
return
Character
To get the represented character of the elem.
type Field tagged record
(
in out
) function Checkargs:
s :
in out Snake.Snake
return
Boolean
Pre
.GameRunning
- the game must be runningPost
.Ghost.GameRunning = (.Ghost.FieldElemAt(s.Pos) = Space) and ((.Ghost.GameRunning and then (.Ghost.FieldElemAt(f.G_PtPos) = Space and .Ghost.PtPos /= s.Pos)) or else not .Ghost.GameRunning)
- FieldElemAt gives the FieldElem at the given pos, and PtPos gives the position of the point.Check if the game can continue or if it must stope.
(
in
) procedure PaintPre
.Ghost.GameRunning
Paint the field without the point.
(
in
) procedure DisplayPtPre
.Ghost.GameRunning
Display the point
(
in out
) procedure NextPointPre
.Ghost.GameRunning and (.Ghost.SnakePos = .Ghost.PtPos or (.Ghost.Context /= null and then .Ghost.Context.Game.Pausing))
- Context return the context of the current game, SnakePos return the current pos of the snakePost .Ghost.PtPos'Old /= .Ghost.PtPos and .Ghost.FieldElemAt(.Ghost.PtPos) = Space and .Ghost.PtPos /= .Ghost.SnakePos;
Set the next point on the field and ensure it is not at the place and inside the field.
(
in
) procedure HidePtPre .Ghost.GamePausing
Hide the point if we are in pause.