So in order for the Computer
to balance the results of the game, we need to add logic to block User
‘s double-opportunity move. In this case, the new procedure
will have a lower priority than Get_Prioritized;
. So in the code used at Get (Computer_Move, App_State);
, we will put the additional new procedure
in between Get_Prioritized;
and Block_Direct_Winning;
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | with Ada.Text_IO; use Ada.Text_IO; package body AI_Mockup is procedure Get ( Computer_Move : out Digit ; App_State : in State ) is begin Get_Prioritized (Computer_Move, App_State); Block_Double_Threat (Computer_Move, App_State); Block_Direct_Winning (Computer_Move, App_State); -- Put_Line ("Computer move:" & Digit'Image (Computer_Move)); end Get; -- Get_Prior... end AI_Mockup; |
And to define for Computer
about User
‘s double chance move, we will still perform an iterative operation to generate predictive states of User_Set
and Common_Set
, and then continue based on this predictive state. calculate the number of winning moves on the next turn.
If the number of winning moves in the last turn is more than 1
, it means that the previous predicted move is a move that creates a Double_Threat
, and we need to assign the value of this predicted move to Computer_Move
to block it. .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | with Ada.Text_IO; use Ada.Text_IO; package body AI_Mockup is -- ... procedure Block_Double_Threat ( Computer_Move : in out Digit ; App_State : in State ) is -- local Foreseen_App_State : State; Foreseen_User_Move : Digit; begin for Index in App_State.Common_Set'Range loop Foreseen_User_Move := App_State.Common_Set (Index); if Foreseen_User_Move /= 0 then Copy (Foreseen_App_State, App_State); Update_User_Set (Foreseen_App_State, Foreseen_User_Move); if Count_Direct_Threat (Foreseen_App_State) > 1 then Computer_Move := Foreseen_User_Move; end if; end if; end loop; end Block_Double_Threat; function Count_Direct_Threat (App_State : State) return Integer is -- local Foreseen_User_Set : Digit_Array; Counter : Integer := 0; begin for Index in App_State.Common_Set'Range loop Foreseen_User_Set (1 .. 9) := App_State.User_Set; Foreseen_User_Set (Index) := App_State.Common_Set (Index); if Found_Winning (Foreseen_User_Set) then Counter := Counter + 1; end if; end loop; -- return Counter; end Count_Direct_Threat; end AI_Mockup; |
Finally, we need to make sure the procedure
are fully declared in the configuration file of the package AI_Mockup
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | with App_Model; use App_Model; package AI_Mockup is procedure Get (Computer_Move : out Digit; App_State : in State); procedure Get_Prioritized (Computer_Move : out Digit; App_State : in State); procedure Block_Direct_Winning (Computer_Move : in out Digit; App_State : in State); procedure Block_Double_Threat (Computer_Move : in out Digit; App_State : in State); function Count_Direct_Threat (App_State : State) return Integer; end AI_Mockup; |
To see if the Computer
was able to balance the outcome of the game in the previous situation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | Choose your Symbol ... 1. Letter 'X' 2. Letter 'O' Your choice: 1 You've chosen: X + - - + - - + - - + | 2 | 9 | 4 | + - - + - - + - - + | 7 | 5 | 3 | + - - + - - + - - + | 6 | 1 | 8 | + - - + - - + - - + Your move: 6 PLAYING ... + - - + - - + - - + | 2 | 9 | 4 | + - - + - - + - - + | 7 | 5 | 3 | + - - + - - + - - + | X | 1 | 8 | + - - + - - + - - + Computer move: 5 PLAYING ... + - - + - - + - - + | 2 | 9 | 4 | + - - + - - + - - + | 7 | O | 3 | + - - + - - + - - + | X | 1 | 8 | + - - + - - + - - + Your move: 4 PLAYING ... + - - + - - + - - + + - - + - - + - - + | 2 | 9 | X | => | | | X | + - - + - - + - - + + - - + - - + - - + | 7 | O | 3 | => | | O | | + - - + - - + - - + + - - + - - + - - + | X | 1 | 8 | => | X | | | + - - + - - + - - + + - - + - - + - - + Computer move: ... PLAYING ... + - - + - - + - - + | | | X | + - - + - - + - - + | | O | | + - - + - - + - - + | X | | O | + - - + - - + - - + |
Oh… So here, when User: X
pre-selects the lower left corner and the upper right corner, the remaining corners are still empty and are all possible moves to create Double_Threat
. If so, even if the Computer
blocks any moves, it will not be able to balance the outcome of the game. Perhaps we still need to add one more processing logic with higher priority than Block_Double_Threat;
.