• Aucun résultat trouvé

Une solution possible L'organisation

Dans le document Apprenez à programmer avec Ada (Page 182-195)

Comme à chaque TP, je compte bien vous fournir une solution. Mais cette solution est bien entendu perfectible. Elle est également complexe et nécessitera quelques explications. Tout d'abord, évoquons l'organisation de mes packages :

Game : la procédure principale. Elle ne contient que très peu de chose, l'essentiel se trouvant dans les packages.

P_Point : propose le type T_Point et les méthodes associées. Ce type permet pour chaque statistique (par exemple la vitesse), de disposer d'une valeur maximale, d'une valeur courante et d'une valeur bonus.

P_Navire : gère les classes, méthodes et interfaces liées aux différents types navires. Ce package aurait du être scindé en plusieurs sous-package pour respecter les règles d'encapsulation. Mais pour que le code gagne en lisibilité et surtout en compacité, j'ai préféré tout réunir en un seul package. Cela vous permettra d'analyser plus facilement le code, les méthodes…

P_Navire.list : le package fils. Celui-ci est fait pour proposer différents navires (frégates, galions, corvette…) au joueur et à l'ordinateur.

P_Variables : gère les variables globales du projet (coût d'une amélioration, temps d'affichage des messages… ) ainsi que les fonctionnalités aléatoires.

P_Data : gère l'enregistrement et la sauvegarde des navires dans des fichiers texte.

P_Screen : gère tous les affichages : affichage de texte accentué, affichage des messages de combat (tir manqué, abordage réussi, fuite…), affichage des différents menus (menu de combat, menu du marché, menus pour choisir entre une nouvelle partie et une ancienne, menu pour choisir le type de bateau sur lequel vous souhaitez naviguer…) P_Modes : package le plus important, c'est lui qui gère tout ce que vous faites au clavier, que ce soit durant les phases de combat, lors de l'affichage du menu du marché… Bref, c'est le cœur du jeu puisqu'il gère les différents modes de jeu.

Attention, les menus sont affichés grâce à P_Screen, mais seulement affichés, leur utilisation se fait grâce à P_Modes.

Le code

Game.adb

Venons-en au code à proprement parler. Voici à quoi se limite la procédure principale : Code : Ada - game.adb

WITH Nt_Console ; USE Nt_Console ; WITH P_Navire ; USE P_Navire ; WITH P_Modes ; USE P_Modes ; PROCEDURE Game IS

BEGIN

set_cursor(visible => false) ; DECLARE

Joueur : T_Navire'Class := first_mode ; BEGIN

market_mode(joueur) ; END ;

END Game ;

On déclare un objet joueur de la classe T_Navire que l'on initialise en lançant First_mode(). Celui-ci proposera de choisir entre créer une nouvelle partie et en charger une ancienne. Dans chacun des cas, un Navire est renvoyé.

Ensuite, on lance le mode marché (Market_mode()) lequel se chargera de lancer les autres modes si besoin est.

P_Point

Ce package présente peu d'intérêt et de difficultés :

Secret (cliquez pour afficher) Code : Ada - P_Point.ads

PACKAGE P_Point IS

TYPE T_Point IS TAGGED RECORD Max, Current, Bonus : Integer ; END RECORD ;

Function "-" (left : T_Point ; right : integer) return integer

; FUNCTION Total (P : T_Point) RETURN Integer ; FUNCTION Ecart(P : T_Point) RETURN Integer ; PROCEDURE Raz(P : OUT T_Point) ;

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 182/312

PROCEDURE Init(P : IN OUT T_Point) ;

PROCEDURE Init(P : IN OUT T_Point ; N : Natural) ; end P_Point ;

Code : Ada - P_Point.adb

PACKAGE BODY P_Point IS

FUNCTION "-" (Left : T_Point ; Right : Integer) RETURN Integer IS BEGIN

RETURN Integer'Max(0,Left.Current - Right) ; END "-" ;

FUNCTION Total(P : T_Point) RETURN Integer IS BEGIN

RETURN P.Current + P.Bonus ; END Total ;

FUNCTION Ecart(P : T_Point) RETURN Integer IS BEGIN T_Illegal. Trois méthodes abstraites sont proposées : Bombarde(), Aborde() et Init(). Des trois, seule Init() est réellement polymorphe. Les deux autres emploient chacune une méthode privée afin de limiter le code. J'aurais pu choisir de modifier le code de bombardement pour les navires de guerre, mais j'ai préféré modifier les statistiques pour accroître les points de Puissance initiaux afin de fournir un avantage initial aux navires de guerre qui peut toutefois être comblé pour les autres navires. Autrement dit, le bonus se fait grâce à Init() mais pas grâce à Bombarde(). Il en est de même pour Aborde(). Cela évite également que le code devienne gigantesque, ce qui ne vous faciliterait pas non plus son analyse.

Code : Ada - P_Navire.ads

WITH P_Point ; USE P_Point ;

WITH Ada.Strings.Unbounded ; USE Ada.Strings.Unbounded ;

PACKAGE P_Navire IS

--TYPES ET METHODES TYPE T_Navire IS ABSTRACT TAGGED RECORD

Nom : Unbounded_string := Null_unbounded_string ;

TYPE T_Stat_Name IS (Coque, Equipage, Puissance, Attaque, Cuirasse, Defense, Vitesse, Gold);

TYPE T_Stat IS ARRAY(T_Stat_Name RANGE coque..Gold) OF Natural ; PROCEDURE Bombarde(Att : IN T_Navire ; Def : in out TYPE T_Illegal IS INTERFACE ; TYPES CONCRETS

TYPE T_Warship IS NEW T_Navire AND T_Legal WITH NULL RECORD ; TYPE T_Tradeship IS NEW T_Navire AND T_Legal WITH RECORD Stock : Integer ;

END RECORD ;

TYPE T_Corsair IS NEW T_Navire AND T_Legal AND T_Illegal WITH NULL RECORD ;

TYPE T_Pirate IS NEW T_Navire AND T_Illegal WITH NULL RECORD ;

--METHODES

OVERRIDING PROCEDURE Bombarde(Att : IN T_Warship ; Def : in out T_Navire'Class) ;

OVERRIDING PROCEDURE Bombarde(Att : IN T_Tradeship ; Def : in out T_Navire'Class) ;

OVERRIDING PROCEDURE Aborde(Att : IN T_Tradeship ; Def : in out T_Navire'Class) is null ;

PROCEDURE Defend(Bateau : IN OUT T_Navire'Class) ; PROCEDURE Manoeuvre(Bateau : IN OUT T_Navire'Class) ; FUNCTION Est_Mort(Bateau : T_Navire'Class) return boolean ; PROCEDURE Raz_Bonus(Bateau : OUT T_Navire'Class) ; PROCEDURE Reparer (Navire : in out T_Navire'Class) ; PROCEDURE Recruter (Navire : in out T_Navire'Class) ; PROCEDURE Vendre (Navire : IN OUT T_Tradeship) ;

PROCEDURE Ameliorer_Coque (Navire : IN OUT T_Navire'Class) ; PROCEDURE Ameliorer_Equipage (Navire : IN OUT T_Navire'Class) ;

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 183/312

PROCEDURE Ameliorer_Puissance(Navire : IN OUT T_Navire'Class) ; PROCEDURE Ameliorer_Attaque (Navire : IN OUT T_Navire'Class) ; PROCEDURE Ameliorer_Cuirasse (Navire : IN OUT T_Navire'Class) ; PROCEDURE Ameliorer_Defense (Navire : IN OUT T_Navire'Class) ; PROCEDURE Ameliorer_Vitesse (Navire : IN OUT T_Navire'Class) ; PROCEDURE Bat(Vainqueur : IN OUT T_Navire'Class ; Perdant : IN T_Navire'Class) ;

PROCEDURE Perd(Navire : IN T_Navire'Class) ; PRIVATE

PROCEDURE Private_Bombarde(Att : IN T_Navire'Class ; Def : IN OUT T_Navire'Class) ;

PROCEDURE Private_Aborde (Att : IN T_Navire'Class ; Def : IN OUT T_Navire'Class) ;

RETURN Random > (Att.Vitesse.total*120 /(Att.Vitesse.total + Def.Vitesse.Total));

END Esquive ;

--CAPACITE DE

PROCEDURE Private_Bombarde(Att : IN T_Navire'class ; Def : in out T_Navire'Class) IS --FORMULE GENERALE END Private_Bombarde ;

OVERRIDING PROCEDURE Bombarde(Att : IN T_Warship ; Def : in out T_Navire'Class) IS --POUR BATEAUX DE GUERRE

BEGIN

Private_Bombarde(Att,Def) ; END Bombarde ;

OVERRIDING PROCEDURE Bombarde(Att : IN T_Tradeship ; Def : in out T_Navire'Class) IS --POUR BATEAUX COMMERCIAUX

BEGIN

PROCEDURE Private_aborde(Att : IN T_Navire'class ; Def : in out T_Navire'Class) IS --FORMULE GENERALE

Navire.Coque.init(Stat(Coque)) ; Navire.Equipage.init (Stat(Equipage)) ; Navire.Puissance.init(Stat(Puissance)*120/100) ; Navire.Attaque.init (Stat(Attaque)) ; Navire.Cuirasse.init (Stat(Cuirasse)) ; Navire.Defense.init (Stat(Defense)) ; Navire.Vitesse.init (Stat(Vitesse)*70/100) ; Navire.Playable := False ;

Navire.Coque.init(Stat(Coque)) ; Navire.Equipage.init (Stat(Equipage)) ; Navire.Puissance.init(Stat(Puissance)*70/100) ; Navire.Attaque.init (Stat(Attaque)) ; Navire.Cuirasse.init (Stat(Cuirasse)*110/100) ; Navire.Defense.init (Stat(Defense)*110/100) ;

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 184/312

Navire.Vitesse.init (Stat(Vitesse)*90/100) ;

Navire.Coque.init(Stat(Coque)) ; Navire.Equipage.init (Stat(Equipage)) ; Navire.Puissance.init(Stat(Puissance)) ; Navire.Attaque.init (Stat(Attaque)) ; Navire.Cuirasse.init (Stat(Cuirasse)) ; Navire.Defense.init (Stat(Defense)) ; Navire.Coque.init(Stat(Coque)) ; Navire.Equipage.init (Stat(Equipage)) ; Navire.Puissance.init(Stat(Puissance)) ; Navire.Attaque.init (Stat(Attaque)*120/100) ; Navire.Cuirasse.init (Stat(Cuirasse)*70/100) ; Navire.Defense.init (Stat(Defense)) ; Navire.Vitesse.init (Stat(Vitesse)*130/100) ; Navire.Playable := False ;

PROCEDURE Defend(Bateau : IN OUT T_Navire'Class) IS BEGIN

Bateau.Defense.Bonus := Bateau.Defense.Current * 25 /100 ; IF Bateau.Playable

THEN Put_Defense_Message(Green) ; ELSE Put_Defense_Message(Light_Red) ; END IF ;

END Defend ;

--CAPACITÉ DE

PROCEDURE Manoeuvre(Bateau : IN OUT T_Navire'Class) IS BEGIN

Bateau.Vitesse.Bonus := Bateau.Vitesse.Current * 25 /100 ; IF Bateau.Playable

THEN Put_Manoeuvre_Message(Green) ; ELSE Put_Manoeuvre_Message(Light_Red) ; END IF ;

END Manoeuvre ;

FONCTION POUR SAVOIR SI UN BATEAU EST COULE FUNCTION Est_Mort(Bateau : T_Navire'Class) RETURN Boolean IS BEGIN

RETURN Bateau.Coque.current = 0 OR Bateau.Equipage.current = 0 ; END Est_Mort ;

REMISE À ZÉRO POUR DBT DE TOUR

PROCEDURE Raz_Bonus(Bateau : OUT T_Navire'Class) IS BEGIN

PROCEDURE Reparer (Navire : IN OUT T_Navire'Class) IS Cout : constant Natural := (Navire.Coque.Max

PROCEDURE Recruter (Navire : IN OUT T_Navire'Class) IS Cout : constant Natural := (Navire.Equipage.max

Navire.Equipage.Current + (Navire.Gold / Recrute_Cost) ; Navire.Gold := Navire.Gold mod Recrute_Cost ; END IF ;

Bleep ; END Recruter ;

PROCEDURE Vendre (Navire : IN OUT T_Tradeship) IS BEGIN

Navire.Gold := Navire.Gold + Navire.Stock * Goods_Cost ; Navire.Stock := 0 ;

Bleep ; END Vendre ;

PROCEDURE Ameliorer_Coque (Navire : IN OUT T_Navire'Class) IS BEGIN END Ameliorer_Coque ;

PROCEDURE Ameliorer_Equipage (Navire : IN OUT T_Navire'Class) IS

END Ameliorer_Equipage ;

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 185/312

PROCEDURE Ameliorer_Puissance(Navire : IN OUT T_Navire'Class)

END Ameliorer_Puissance ;

PROCEDURE Ameliorer_Attaque (Navire : IN OUT T_Navire'Class) IS cout : constant natural := Attaque_Cost *

END Ameliorer_Attaque ;

PROCEDURE Ameliorer_Cuirasse (Navire : IN OUT T_Navire'Class) IS BEGIN

END Ameliorer_Cuirasse ;

PROCEDURE Ameliorer_Defense (Navire : IN OUT T_Navire'Class) IS cout : constant natural := Defense_Cost *

END Ameliorer_Defense ;

PROCEDURE Ameliorer_Vitesse (Navire : IN OUT T_Navire'Class) IS

END Ameliorer_Vitesse ; --GAIN DE FIN DE

PROCEDURE Bat(Vainqueur : IN OUT T_Navire'Class ; Perdant : IN T_Navire'Class) IS

Put("Vous remportez " & integer'image(Gain_or) & " or") ; IF Vainqueur IN T_Tradeship'Class

PROCEDURE Perd(Navire : IN T_Navire'Class) IS BEGIN massacr" & Character'Val(130) & ".") ;

END IF ;

Peu d'intérêt, c'est ici que sont écrits les statistiques des différents navires (frégate, trois-mâts, galion et corvette). Vous pouvez en ajouter autant que bon vous semble. Le seul inconvénient, c'est qu'il faudra recompiler le code source (les données sont hard-coded).

Secret (cliquez pour afficher) Code : Ada - p_navire-list.ads

package P_Navire.List is TYPE T_Navire_Id IS RECORD Nom : Unbounded_String ; Stat : T_Stat ; END RECORD ;

type T_Liste_Navire is array(positive range <>) of T_Navire_Id

;

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 186/312

10, 300) ;

Liste_Navire : T_Liste_Navire :=(

(To_Unbounded_String("Frégate"), Stat_Fregate), (To_Unbounded_String("Gallion"), Stat_Gallion), (To_Unbounded_String("Corvette"), Stat_Corvette), (To_Unbounded_String("Trois-Mâts"), Stat_Trois_Mats) );

GÉNÉRATION D'ADVERSAIRES

PROCEDURE Mettre_Niveau(Navire : IN OUT T_Navire'Class ; Niveau : Positive) ;

FUNCTION Generer_Ennemi(Niveau : Natural := 1) RETURN T_Navire'Class ;

End P_Navire.List ;

Code : Ada - p_navire-list.adb

WITH P_Variables ; USE P_Variables ; package body P_Navire.List is

PROCEDURE Mettre_Niveau(Navire : IN OUT T_Navire'Class ; Niveau : Positive) IS

coef : float ; BEGIN

Coef := 1.5**(Niveau-1) ;

Navire.Coque.Init(Integer(Float(Navire.Coque.Max) * Coef)) ; Navire.Equipage.Init(Integer(Float(Navire.Equipage.Max) * Coef)) ;

Navire.Puissance.Init(Integer(Float(Navire.Puissance.Max) * Coef)) ;

Navire.Attaque.Init(Integer(Float(Navire.Attaque.Max) * Coef)) ;

Navire.Cuirasse.Init(Integer(Float(Navire.Cuirasse.Max) * Coef)) ;

Navire.Defense.Init(Integer(Float(Navire.Defense.Max) * Coef)) ;

Navire.Vitesse.Init(Integer(Float(Navire.Vitesse.Max) * Coef)) ;

Coef := 2.0**(Niveau-1) ;

Navire.Gold := integer(float(Navire.Gold) * coef) ; END Mettre_Niveau ;

FUNCTION Generer_Ennemi(Niveau : Natural := 1) RETURN T_Navire'Class IS

Mettre_Niveau(Navire.All,Niveau) ; RETURN Navire.all ;

END Generer_Ennemi ; End P_Navire.List ;

P_Variables

Là encore peu d'intérêt, hormis si vous souhaitez modifier le temps d'affichage des message, le coût de base d'une amélioration ou des réparations.

Secret (cliquez pour afficher) Code : Ada - P_Variables.ads

WITH Ada.Strings.Unbounded ; USE Ada.Strings.Unbounded ; WITH Ada.Numerics.Discrete_Random ;

PACKAGE P_Variables IS

subtype T_Pourcentage is integer range 0..100 ;

PACKAGE P_Random IS NEW

Ada.Numerics.Discrete_Random(T_Pourcentage) ; Germe : P_Random.Generator ;

PROCEDURE Reset ;

FUNCTION Random RETURN T_Pourcentage ; Message_Time : CONSTANT Duration := 2.0 ;

Save_File_Name : unbounded_string := Null_unbounded_string ;

PRIVATE

PROCEDURE Reset(G : P_Random.Generator) RENAMES P_Random.Reset

; FUNCTION Random(G : P_Random.Generator) RETURN T_Pourcentage RENAMES P_Random.Random ;

FUNCTION Random RETURN T_Pourcentage IS BEGIN

RETURN Random(Germe) ; END Random ;

end P_Variables ;

P_Data

Comme dit précédemment, ce package sert à l'enregistrement et au chargement de parties enregistrées dans des fichiers texte.

Bref, c'est du déjà-vu pour vous : Secret (cliquez pour afficher)

Code : Ada - P_Data.ads

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 187/312

WITH P_Navire ; USE P_Navire ; PACKAGE P_Data IS

FUNCTION Load_Navire(File_Name : String) RETURN T_Navire'Class

; PROCEDURE Save_Navire(Navire : in T_Navire'class) ;

end P_Data ;

Code : Ada - P_Data.adb

WITH Ada.Text_IO ; USE Ada.Text_IO ; WITH Ada.Strings.Unbounded ; USE Ada.Strings.Unbounded ; WITH P_Variables ; USE P_Variables ; WITH P_Point ; USE P_Point ;

PACKAGE BODY P_Data IS

FUNCTION Load_Navire(File_Name : String) RETURN T_Navire'Class IS FUNCTION Value(F : File_type) RETURN Integer IS

Open(F, In_File,"./data/" & File_Name & ".txt") ; CASE Value(F) IS

PROCEDURE Save_Navire(Navire : in T_Navire'class) IS F : File_Type ;

Create(F,Out_File,"./data/" & to_string(Save_File_Name) &

".txt") ; Put_Line (F, Integer'Image(Navire.Gold)) ; IF Navire IN T_Tradeship'Class THEN Put_Line(F,

Integer'Image(T_Tradeship(Navire).Stock)) ; END IF ;

Put_Line (F, Integer'Image(Coque_Cost)) ; Put_Line (F, Integer'Image(Equipage_Cost)) ; Put_Line (F, Integer'Image(Puissance_Cost)) ; Put_Line (F, Integer'Image(Attaque_Cost)) ; Put_Line (F, Integer'Image(Cuirasse_Cost)) ; Put_Line (F, Integer'Image(Defense_Cost)) ; Put_Line (F, Integer'Image(Vitesse_Cost)) ; Close(F) ;

END Save_Navire ; END P_Data ;

P_Screen

Package important : c'est là que se font tous les affichages.

Code : Ada - P_Screen.ads

WITH Nt_Console ; USE Nt_Console ; WITH P_Navire ; USE P_Navire ; WITH P_Point ; USE P_Point ; PACKAGE P_Screen IS

TYPE T_Position IS (Gauche, Droite) ;

PROCEDURE Put(N : Integer ; Color : Color_Type := Black ; X,Y : Integer := -1) ;

PROCEDURE Print(Text : String ; Color : Color_Type := Black ; X,Y : Integer := -1) ;

PROCEDURE Put_Title ;

PROCEDURE Put_First_Menu(Indice : Natural := 1) ; PROCEDURE Put_Fight_Menu(Navire : T_Navire'Class ; Indice : Natural := 1) ;

PROCEDURE Put_NextFight_Menu(Indice : Natural := 1) ;

PROCEDURE Put_Status(Navire : T_Navire'class ; Pos : T_Position := Gauche) ;

PROCEDURE Put_Point(Point : T_Point) ;

PROCEDURE Put_Esquive_Message(Color : Color_Type := Green) ; PROCEDURE Put_Bombard_Message(Degats : Integer ; Color : Color_Type := Green) ;

PROCEDURE Put_Abordage_Message(Degats : Integer ; Color : Color_Type := Green) ;

PROCEDURE Put_Defense_Message(Color : Color_Type := Green) ; PROCEDURE Put_Manoeuvre_Message(color : color_type := green) ; PROCEDURE Put_Fuite_Message ;

PROCEDURE Put_Gold(Navire : T_Navire'class ; X : X_Pos := 40 ; Y : Y_Pos := 16) ;

PROCEDURE Put_Market_Menu1(Navire : T_Navire'Class ; Indice : Natural := 1) ;

PROCEDURE Put_Market_Menu2(Indice : Natural := 1) ; PROCEDURE Put_Select_Menu1(Indice : Natural := 1) ; PROCEDURE Put_Select_Menu2(Indice : Natural := 1) ;

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 188/312

end P_Screen ; WITH Ada.Strings.Unbounded ; USE Ada.Strings.Unbounded ; WITH Ada.Integer_Text_IO ;

Set_Foreground(Color) ; Set_BackGround(White) ; Ada.Integer_Text_IO.put(n,0) ;

Set_Foreground(Color) ; Set_BackGround(White) ; FOR I IN Text'RANGE LOOP PROCEDURE Put_Title IS BEGIN

PROCEDURE Put_First_Menu(Indice : Natural := 1) IS X : constant Natural := 9 ;

Y : CONSTANT Natural := 4 ; color : color_type := blue ; BEGIN

Print("Que souhaitez-vous faire ?",color,0,Y-1) ; FOR I IN 1..2 LOOP

PROCEDURE Put_Fight_Menu(Navire : T_Navire'Class ; Indice : Natural:=1) IS

PROCEDURE Put_NextFight_Menu(Indice : Natural := 1) IS X : constant Natural := 9 ;

Print("Que souhaitez-vous faire désormais ?",color,0,Y) ; FOR I IN 1..3 LOOP

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 189/312

END LOOP ;

Goto_Xy(X+20*(Indice-1) + 3,Y+2) ; Set_Foreground(Light_Red) ; Put(Character'Val(30)) ; set_foreground(black) ; END Put_Nextfight_Menu ;

--AFFICHAGE DU STATUS D'UN

PROCEDURE Put_Status(Navire : T_Navire'class ; Pos : T_Position := Gauche) is Set_Foreground(Light_Red) ; Goto_Xy(X,Y+1) ;

Put(" " & Character'Val(2) & " ") ; put_point(Navire.coque)

; Set_Foreground(Green) ; Goto_Xy(X,Y+2) ; Put(" " & Character'Val(3) & " ") ; Put_Point(Navire.Equipage) ;

Goto_Xy(X,Y+3) ; Put("Psce:") ; Put_Point(Navire.Puissance)

; Goto_Xy(X,Y+4) ; Put("Attq:") ; Put_Point(Navire.Attaque) ; Goto_Xy(X,Y+5) ; Put("Cuir:") ; Put_Point(Navire.Cuirasse) ; Goto_Xy(X,Y+6) ; Put("Dfns:") ; Put_Point(Navire.Defense) ; Goto_Xy(X,Y+7) ; Put("Vits:") ; Put_Point(Navire.Vitesse) ; END Put_Status ;

--AFFICHAGE DU TYPE PROCEDURE Put_Point(Point : T_Point) IS BEGIN

PROCEDURE Put_Esquive_Message(color : color_type := green) IS BEGIN ELSE Set_Foreground(light_Red) ;

Put("L'adversaire a esquiv"& character'val(130) &" votre attaque !") ;

Set_Foreground(Black) ; END IF ;

delay message_time ; END Put_Esquive_Message ;

PROCEDURE Put_Bombard_Message(Degats : Integer ; Color : Color_Type := Green) IS

ELSE Put("Le bombardement ennemi a caus"& Character'Val(130)

& " ") ; END Put_Bombard_Message ;

PROCEDURE Put_Abordage_Message(Degats : Integer ; Color : Color_Type := Green) IS

ELSE Put("L'abordage ennemi a tu"& Character'Val(130) & " ")

; Put(degats,light_red) ; put(" de vos marins") ; END IF ;

DELAY message_time ; END Put_Abordage_Message ;

PROCEDURE Put_Defense_Message(color : color_type := green) IS BEGIN ELSE Set_Foreground(light_Red) ;

Put("L'ennemi se pr"& character'val(130) &"pare "&

character'val(133) &" l'abordage !") ; Set_Foreground(Black) ; END IF ;

delay Message_time ; END Put_Defense_Message ;

PROCEDURE Put_Manoeuvre_Message(color : color_type := green) IS BEGIN

ELSE Set_Foreground(light_Red) ;

Put("Le navire ennemi se place sous le vent !") ; Set_Foreground(Black) ;

END IF ; delay Message_time ; END Put_Manoeuvre_Message ; PROCEDURE Put_Fuite_Message IS BEGIN

goto_xy(0,11) ; Set_Foreground(light_Red) ;

Put("Vous fuyez devant l'adversit" & character'val(130) & "

!") ;

Set_Foreground(Black) ; delay Message_time ; END Put_Fuite_Message ; --AFFICHAGE DES MENUS DU

---Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 190/312

PROCEDURE Put_Gold(Navire : T_Navire'class ; X : X_Pos := 40 ;

Put(Integer'Image(Navire.Gold)) ; Set_Foreground(Black) ; END Put_Gold ;

PROCEDURE Put_Market_Menu1(Navire : T_Navire'Class ; Indice : Natural := 1) IS END Put_Market_Menu1 ;

PROCEDURE Put_Market_Menu2(Indice : Natural := 1) IS X : constant Natural := 35 ;

integer'image(Vitesse_cost) & ") + 1 Vitesse") ; WHEN 2 => Put(" B o u c l i e r s (" &

integer'image(Defense_cost) & "/marin) + 1 Defense") ; WHEN 3 => Put(" B l i n d a g e (" &

integer'image(Cuirasse_cost) & ") + 1 Cuirasse") ;

WHEN 4 => Put("Sabres (" & integer'image(Attaque_cost)

& "/marin) + 1 Attaque") ;

WHEN 5 => Put(" C a n n o n s (" &

integer'image(Puissance_cost) & ") + 1 Puissance") ; WHEN 6 => Put("Couchettes (" &

integer'image(Equipage_cost) & ") + 2 Equipage");

WHEN 7 => Put("Planches (" & integer'image(Coque_cost) END Put_Market_Menu2 ;

PROCEDURE Put_Select_Menu1(Indice : Natural := 1) IS BEGIN END Put_Select_Menu1 ;

PROCEDURE Put_Select_Menu2(Indice : Natural := 1) IS color : color_type ;

print(to_string(Liste_navire(i).nom),color,22,i+3) ; END LOOP ;

set_foreground(black) ; END Put_Select_Menu2 ; end P_Screen ;

P_Modes

Et enfin, le cœur du jeu : P_Mode. C'est dans ce dernier package que sont gérés les touches du clavier et la réaction à adopter.

Code : Ada - P_Modes.ads

WITH P_Navire ; USE P_Navire ;

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 191/312

PACKAGE P_Modes IS

FUNCTION First_Mode RETURN T_Navire'Class ; PROCEDURE Fight_Mode (Joueur : IN OUT T_Navire'Class) ; FUNCTION NextFight_Mode RETURN natural ;

PROCEDURE Market_Mode(Joueur : IN OUT T_Navire'Class) ; PROCEDURE Buy_Mode(Joueur : IN OUT T_Navire'Class) ; FUNCTION Select_Mode RETURN T_Navire'class ; END P_Modes ;

Le nombre de procédures et fonctions est restreint : First_Mode() gère le tout premier menu pour choisir entre une nouvelle ou une ancienne partie ; en cas de nouvelle partie, il lancera Select_Mode() qui permet au joueur de choisir son navire et sa classe (marchand, pirate…) ; puis il accède au menu du marché, Market_Mode() qui est le principal menu (c'est de là que se font les sauvegardes en appuyant sur Echap, les achats avec Buy_Mode(), les ventes, les réparations ou le départ en mer avec Fight_Mode()) ; enfin, NextFight_Mode() gère un menu proposant au joueur de rentrer au port ou de continuer son aventure à la fin de chaque combat.

Secret (cliquez pour afficher) Code : Ada - P_Modes.adb

WITH Ada.Text_IO ; USE Ada.Text_IO ; WITH Ada.Strings.Unbounded ; USE Ada.Strings.Unbounded ; WITH Nt_Console ; USE Nt_Console ;

FUNCTION First_Mode RETURN T_Navire'Class IS Position : Natural := 1 ;

PROCEDURE Fight_Mode(Joueur : IN OUT T_Navire'Class) IS Touche : Character ;

Position : Natural := 4 ; N : T_Pourcentage ;

Ordi : T_Navire'Class := generer_ennemi(Niveau) ; BEGIN

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 192/312

END IF ; END LOOP Main_loop ; END Fight_Mode ;

FUNCTION NextFight_Mode RETURN natural IS Position : Natural := 1 ;

PROCEDURE Market_Mode(Joueur : IN OUT T_Navire'Class) IS Position : Natural := 1 ; T_Tradeship'class and position = 4) or position < 4) THEN Position := Position + 1 ;

PROCEDURE Buy_Mode(Joueur : IN OUT T_Navire'Class) IS Position : Natural := 1 ;

FUNCTION Select_Mode RETURN T_Navire'Class IS Navire : ACCESS T_Navire'Class ;

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 193/312

Menu2 : LOOP

Put_Select_Menu2(Pos2) ; Touche := Get_Key ; --touche haut

IF Character'Pos(Touche) = 72 and pos2 > 1 THEN pos2 := pos2 - 1 ;

END IF ; --touche bas

IF Character'Pos(Touche) = 80 and pos2 <

Liste_Navire'length

THEN pos2 := pos2 + 1 ; END IF ;

--touche entrée ou droite

IF Character'Pos(Touche) = 13 or Character'Pos(Touche)

= 77 THEN bleep ; EXIT Main_Loop ; END IF;

IF Character'Pos(Touche) = 75 THEN EXIT Menu2 ; END IF;

END LOOP Menu2 ; END LOOP Main_loop ; CASE Pos1 IS

WHEN 1 => Navire := NEW

T_Warship'(Init(Liste_Navire(Pos2).nom, Liste_Navire(Pos2).stat))

; WHEN 2 => Navire := NEW T_Tradeship'(Init(Liste_Navire(Pos2).nom, Liste_Navire(Pos2).stat)) ;

WHEN 3 => Navire := NEW

T_Pirate'(Init(Liste_Navire(Pos2).nom, Liste_Navire(Pos2).stat)) ; WHEN others => Navire := NEW

T_Corsair'(Init(Liste_Navire(Pos2).nom, Liste_Navire(Pos2).stat))

; END CASE ;

Navire.Playable := True ; Navire.Gold := 100 ; return Navire.all ; END Select_Mode ; END P_Modes ;

Pistes d'amélioration :

Ajouter un écran affichant les meilleurs scores obtenus, les navires les plus puissants, les plus riches, les plus peuplés…

Ajouter une nationalité à votre navire (français, anglais, portugais, hollandais, espagnol, pirate…) ajoutant de nouveaux bonus/malus ou proposant des navires spécifiques.

Vous pouvez également approfondir le système de jeu en proposant de personnaliser les armes (grappins, filets, sabres, lances, petits ou gros cannons…) ou les manœuvres, ou encore de changer pour un navire plus performant.

Pourquoi ne pas proposer un jeu en deux temps : des phases de bataille navale (ce que vous venez de créer) et des phases d'exploration où le joueur devrait déplacer son navire sur une carte.

Partie 4 : Ada : Notions avancées et Programmation Orientée Objet 194/312

Dans le document Apprenez à programmer avec Ada (Page 182-195)