Description
Connect Four has been contributed by Professors Barry Fagin and Martin Carlisle of the US Air Force Academy for the JVM-GNAT version and has been adapted to GNOGA by Pascal Pignard. JVM-GNAT code has been left as comments in order to show the translation to Gnoga.
You can play the game by using your mouse to click on the column where you want to make your move. After some thinking the program will respond with its own move. You win if you can align 4 circles in a straight line (vertically, horizontally, or diagonally). When a winning position is reached you can restart the game by clicking on the mouse.
This application uses Zanyblue. Before running connect four, set the language variable for Zanyblue, for instance: (replace fr_FR by your own local language) unix like: export LANG=fr_FR.UTF-8.
Source code
connectfour.ads
--------------------------------------------------------------
-- Connect Four (TM) GNAPPLET
--
-- By: Barry Fagin and Martin Carlisle
-- US Air Force Academy, Department of Computer Science
-- mailto:carlislem@acm.org
--
-- 20150511 Adapted from JVM-GNAT to GNOGA by Pascal Pignard
-- http://blady.pagesperso-orange.fr
--
-- This is free software; you can redistribute it and/or
-- modify without restriction. We do ask that you please keep
-- the original author information, and clearly indicate if the
-- software has been modified.
--
-- This software is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
--------------------------------------------------------------
-- with Java.Awt.Event.Mouselistener;
-- with Java.Awt.Event.MouseEvent;
-- with Java.Awt.Image;
-- with Java.Awt.Image.ImageObserver;
-- with Java.Awt.Graphics;
-- with Java.Applet.Applet;
-- with Java.Lang.String;
-- with Java.IO.Serializable;
-- with Java.Awt.MenuContainer;
-- with Javax.Accessibility.Accessible;
with Gnoga.Gui.View;
with Gnoga.Gui.Base; use Gnoga.Gui.Base;
with Gnoga.Gui.Element.Canvas.Context_2D;
with Gnoga.Gui.Window;
with ZanyBlue.Text.Locales;
package ConnectFour is
Num_Rows : constant Integer := 6;
Num_Columns : constant Integer := 7;
-- Constants for the board size
type Player_Kind is (None, Computer, User);
-- None means that neither the computer, nor the user have selected that
-- circle, Computer indicates that the circle has been selected by the
-- computer and User means that the circle has been selected by the user.
-- data type for the Connect Four board
type Board_Array_Type is array (1 .. Num_Rows, 1 .. Num_Columns) of Player_Kind;
-- Adding these discriminants to a type is the magic way of
-- telling JVM-GNAT that you are implementing these interfaces.
type Typ
-- (I_Serializable : java.io.Serializable.Ref;
-- I_MenuContainer : java.awt.MenuContainer.Ref;
-- I_ImageObserver : java.awt.image.ImageObserver.Ref;
-- I_MouseListener : Java.Awt.Event.Mouselistener.Ref;
-- I_Accessible : Javax.Accessibility.Accessible.Ref)
is new Gnoga.Gui.View.View_Type with record
User_Turn : Boolean;
The_Canvas : Gnoga.Gui.Element.Canvas.Canvas_Type;
Main_Window : Gnoga.Gui.Window.Window_Access;
-- state
Board : Board_Array_Type; -- the current board
-- Is the game over, and if so who won?
Computer_Won : Boolean := False;
User_Won : Boolean := False;
Tie : Boolean := False;
-- if user clicks in full column, computer should not take a turn
-- Also computer should not take turn if user wins or tie.
Ignore_Turn : Boolean := False;
Locale : ZanyBlue.Text.Locales.Locale_Type;
end record;
type Ref is access all Typ'Class;
-- pragma Convention (Java, Typ);
-- The following are the specifications for the overridden
-- methods from the Applet and MouseListener interfaces
function GetAppletInfo
(This : access Typ)
return Gnoga.String;
procedure Init (This : access Typ);
procedure Paint
(This : access Typ;
G1 : access Gnoga.Gui.Element.Canvas.Context_2D.Context_2D_Type);
-- procedure Update
-- (This : access Typ;
-- G : access Java.Awt.Graphics.Typ'Class);
procedure mouseReleased
(This : in out Base_Type'Class;
E : in Mouse_Event_Record);
-- pragma Convention (Java, MouseReleased);
-- procedure mouseClicked (This : access Typ;
-- P1 : access java.awt.event.MouseEvent.Typ'Class);
-- pragma Convention (Java, MouseClicked);
--
-- procedure mouseEntered (This : access Typ;
-- P1 : access java.awt.event.MouseEvent.Typ'Class);
-- pragma Convention (Java, MouseEntered);
--
-- procedure mouseExited (This : access Typ;
-- P1 : access java.awt.event.MouseEvent.Typ'Class);
-- pragma Convention (Java, MouseExited);
procedure mousePressed
(This : in out Base_Type'Class;
E : in Mouse_Event_Record);
-- pragma Convention (Java, MousePressed);
end ConnectFour;
adablog-controller.ads
with Gnoga.Gui.Window;
with Gnoga.Application.Multi_Connect;
package AdaBlog.Controller is
procedure Index
(Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
Connection : access Gnoga.Application.Multi_Connect.Connection_Holder_Type);
procedure New_Entry
(Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
Connection : access Gnoga.Application.Multi_Connect.Connection_Holder_Type);
procedure Log_Out
(Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
Connection : access Gnoga.Application.Multi_Connect.Connection_Holder_Type);
end AdaBlog.Controller;
adablog-controller.adb
with Ada.Calendar;
with Gnoga.Types;
with Gnoga.Gui.Base;
with Gnoga.Gui.Element;
with Gnoga.Gui.Element.Common;
with Gnoga.Gui.Element.Form;
with AdaBlog.View;
with AdaBlog.Model;
package body AdaBlog.Controller is
procedure On_Create_User (Object : in out Gnoga.Gui.Base.Base_Type'Class);
-- The create user button was clicked
procedure On_User_Login (Object : in out Gnoga.Gui.Base.Base_Type'Class);
-- User clicked the submit button for his user name and password
procedure On_Submit_Entry (Object : in out Gnoga.Gui.Base.Base_Type'Class);
-- User clicked the submit button to an a blog entry.
procedure On_Create_User (Object : in out Gnoga.Gui.Base.Base_Type'Class) is
Main_Window : aliased Gui.Window.Window_Type;
Message_Area : Gui.Element.Common.DIV_Type;
User_Login : Gui.Element.Common.Button_Type;
username : Gui.Element.Form.Text_Type;
password : Gui.Element.Form.Text_Type;
pass2 : Gui.Element.Form.Text_Type;
verify : Gui.Element.Common.DIV_Type;
User : AdaBlog.Model.Users.Active_Record;
begin
Main_Window.Attach (Object.Connection_ID);
Message_Area.Attach_Using_Parent (Main_Window, "message");
User_Login.Attach_Using_Parent (Main_Window, "login-button");
User_Login.Disabled;
username.Attach_Using_Parent (Main_Window, "username");
password.Attach_Using_Parent (Main_Window, "pass");
pass2.Attach_Using_Parent (Main_Window, "pass2");
verify.Attach_Using_Parent (Main_Window, "verify-pass");
verify.Display ("inline");
if Gnoga.String'(password.Value) /= Gnoga.String'(pass2.Value) or pass2.Value = "" then
Message_Area.Text ("Please verify password.");
return;
end if;
if username.Value = "" then
Message_Area.Text ("Username is required.");
return;
end if;
User.Find_Where ("username='" & username.Value & "'");
if User.Value ("id") /= "" then
Message_Area.Text ("Username is already taken.");
return;
end if;
User.Value ("username", Value => username.Value);
User.Value ("pass", Value => password.Value);
User.Value ("last_session", Value => Main_Window.Gnoga_Session_ID);
User.Save;
Main_Window.Location.URL ("/");
end On_Create_User;
procedure On_User_Login (Object : in out Gnoga.Gui.Base.Base_Type'Class) is
Main_Window : aliased Gui.Window.Window_Type;
Message_Area : Gui.Element.Common.DIV_Type;
username : Gui.Element.Form.Text_Type;
password : Gui.Element.Form.Text_Type;
User : AdaBlog.Model.Users.Active_Record;
begin
Main_Window.Attach (Object.Connection_ID);
Message_Area.Attach_Using_Parent (Main_Window, "message");
username.Attach_Using_Parent (Main_Window, "username");
password.Attach_Using_Parent (Main_Window, "pass");
User.Find_Where
(Where => "username ='" & username.Value & "'" & " AND " & "pass ='" & password.Value & "'",
Create_New => False);
User.Value ("last_session", Value => Main_Window.Gnoga_Session_ID);
User.Save;
Main_Window.Location.URL ("/");
exception
when others =>
Message_Area.Text ("Invalid Login");
end On_User_Login;
procedure On_Submit_Entry (Object : in out Gnoga.Gui.Base.Base_Type'Class) is
User : AdaBlog.Model.Users.Active_Record;
Entries : AdaBlog.Model.Blog_Entries.Active_Record;
Main_Window : aliased Gui.Window.Window_Type;
Text : Gnoga.Gui.Element.Form.Text_Area_Type;
begin
Main_Window.Attach (Object.Connection_ID);
Text.Attach_Using_Parent (Main_Window, "entry_text");
User.Find_Where ("last_session ='" & Main_Window.Gnoga_Session_ID & "'");
Entries.Value ("user_id", Value => User.Value ("id"));
Entries.Value ("entry_date", Date_Value => Ada.Calendar.Clock);
Entries.Value ("entry_text", Value => Text.Value);
Entries.Save;
Main_Window.Location.URL ("/");
end On_Submit_Entry;
procedure Index
(Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
Connection : access Gnoga.Application.Multi_Connect.Connection_Holder_Type)
is
Content_Area : Gui.Element.Common.DIV_Type;
Left_Area : Gui.Element.Common.DIV_Type;
User_Login : Gui.Element.Common.Button_Type;
Create_User : Gui.Element.Common.Button_Type;
User : AdaBlog.Model.Users.Active_Record;
procedure Display_Row (Row : Gnoga.Types.Data_Map_Type);
procedure Display_Row (Row : Gnoga.Types.Data_Map_Type) is
begin
AdaBlog.View.Display_Blog_Entry (Content_Area, Row);
end Display_Row;
begin
User.Find_Where ("last_session ='" & Main_Window.Gnoga_Session_ID & "'");
Main_Window.Disable_Auto_Set_View;
Content_Area.Create (Parent => Main_Window, ID => "main-body");
AdaBlog.Connection.Iterate
(SQL =>
"select username, entry_date, entry_text " & "from users, blog_entries " &
"where users.id=blog_entries.user_id",
Process => Display_Row'Unrestricted_Access);
View.User_Panel (Main_Window => Main_Window, Panel => Left_Area, User_Record => User.Values);
View.Template (Main_Window => Main_Window, Content => Content_Area, Left_Panel => Left_Area);
User_Login.Attach_Using_Parent (Main_Window, "login-button");
User_Login.On_Click_Handler (On_User_Login'Access);
Create_User.Attach_Using_Parent (Main_Window, "create-button");
Create_User.On_Click_Handler (On_Create_User'Access);
Connection.Hold;
end Index;
procedure New_Entry
(Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
Connection : access Gnoga.Application.Multi_Connect.Connection_Holder_Type)
is
User : AdaBlog.Model.Users.Active_Record;
Content_Area : Gui.Element.Common.DIV_Type;
Left_Area : Gui.Element.Common.DIV_Type;
Submit : Gui.Element.Common.Button_Type;
begin
User.Find_Where ("last_session ='" & Main_Window.Gnoga_Session_ID & "'");
if User.Value ("id") = "" then
Main_Window.Location.URL ("/");
return;
end if;
Main_Window.Disable_Auto_Set_View;
View.New_Entry_Form (Main_Window => Main_Window, Content => Content_Area);
View.User_Panel (Main_Window => Main_Window, Panel => Left_Area, User_Record => User.Values);
View.Template (Main_Window => Main_Window, Content => Content_Area, Left_Panel => Left_Area);
Submit.Attach_Using_Parent (Main_Window, "submit_entry");
Submit.On_Click_Handler (On_Submit_Entry'Access);
Connection.Hold;
end New_Entry;
procedure Log_Out
(Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
Connection : access Gnoga.Application.Multi_Connect.Connection_Holder_Type)
is
pragma Unreferenced (Connection);
User : AdaBlog.Model.Users.Active_Record;
begin
User.Find_Where ("last_session ='" & Main_Window.Gnoga_Session_ID & "'");
if User.Value ("id") /= "" then
User.Value ("last_session", "");
User.Save;
end if;
Main_Window.Location.URL ("/");
end Log_Out;
begin
Application.Multi_Connect.On_Connect_Handler (Controller.Index'Unrestricted_Access, "default");
Application.Multi_Connect.On_Connect_Handler (Controller.Index'Unrestricted_Access, "main");
Application.Multi_Connect.On_Connect_Handler (New_Entry'Unrestricted_Access, "new_entry");
Application.Multi_Connect.On_Connect_Handler (Log_Out'Unrestricted_Access, "logout");
end AdaBlog.Controller;
connectfour.adb
--------------------------------------------------------------
-- Connect Four (TM) GNAPPLET
--
-- By: Barry Fagin and Martin Carlisle
-- US Air Force Academy, Department of Computer Science
-- mailto:carlislem@acm.org
--
-- 20150613 Adapted from JVM-GNAT to GNOGA by Pascal Pignard
-- http://blady.pagesperso-orange.fr
--
-- This is free software; you can redistribute it and/or
-- modify without restriction. We do ask that you please keep
-- the original author information, and clearly indicate if the
-- software has been modified.
--
-- This software is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
--------------------------------------------------------------
-- with Java.Lang.String; use Java.Lang.String;
-- with Java; use Java;
-- with Java.Applet.Applet; use Java.Applet.Applet;
-- with Java.Awt.Color;
-- with Java.Awt.Dimension;
-- with Java.Awt.Graphics; use Java.Awt.Graphics;
-- with Java.Net.Url;
-- with Java.Awt.Component;
-- The following comments are adapted from the JGNAT Tic-Tac-Toe
-- example program (C) Ada Core Technologies
--
-- * In the Init function of your applet, you need to call
-- Adainit subprogram to elaborate your program. In the
-- case of this applet it's ada_connectfour.adainit.
--
-- To execute the applet, you need to run the Java appletviewer
-- or a Java-capable browser on an html file such as the following:
--
-- <html>
-- <head>
-- <title>Connect Four (TM) Game, written in Ada</title>
-- </head>
--
-- <body>
--
-- <h1>Built using JVM-GNAT, The Ada 2005 to JVM compiler </h1>
--
-- <P ALIGN=center>
--
-- <APPLET CODEBASE="."
-- CODE="connectfour$typ.class"
-- ARCHIVE="connectfour.jar"
-- WIDTH=500 HEIGHT=300>
-- Sorry, can't show the applet</APPLET>
--
-- </P>
--
-- <hr>
-- </body>
-- </html>
--
-- See the Makefile provided in the directory for this demo
-- for specific details on how to create and run the applet.
with Gnoga.Types.Colors;
with connectfour_messages.connectfour_Strings; use connectfour_messages.connectfour_Strings;
package body ConnectFour is
use all type Gnoga.String;
subtype String is Gnoga.String;
------------------------
-- Local Types & Data --
------------------------
-- Num_Rows : constant Integer := 6;
-- Num_Columns : constant Integer := 7;
-- Constants for the board size
-- type Player_Kind is (None, Computer, User);
-- None means that neither the computer, nor the user have selected that
-- circle, Computer indicates that the circle has been selected by the
-- computer and User means that the circle has been selected by the user.
-- data type for the Connect Four board
-- type Board_Array_Type is array (1 .. Num_Rows, 1 .. Num_Columns)
-- of Player_Kind;
-- This image is used for double-buffering. See the update
-- method.
-- Off_Screen_Buffer : access Java.Awt.Image.Typ'Class;
-- use type Java.Awt.Image.Ref;
-- globals that maintain state -> put in Typ record for concurrency
-- Board : Board_Array_Type; -- the current board
-- Is the game over, and if so who won?
-- Computer_Won : Boolean := False;
-- User_Won : Boolean := False;
-- Tie : Boolean := False;
-- if user clicks in full column, computer should not take a turn
-- Also computer should not take turn if user wins or tie.
-- Ignore_Turn : Boolean := False;
-- The following constants are used to define the layout of the
-- board. They define the horizontal and vertical spacing of the
-- circles drawn on the screen.
Ytop : constant := 20; -- highest pos on screen
Ybottom : constant := 279; -- lowest pos on screen
Xleft : constant := 0; -- leftmost pos on screen
Xright : constant := 499; -- rightmost pos on screen
Title_Offset : constant := 4; -- left move from center of column
Title_Height : constant := 12; -- height of column numbers
-- Both horizontally and vertically, there are circles and intervals
-- (or spaces) between the circles.
-- If there is half an interval on the left and right ends, then
-- there are 7 full intervals (because there are 6 full intervals
-- not counting the ends) horizontally
-- Now, assuming the intervals are 1/4th as wide as the circles
-- (The 1/4th is completely arbitrary),
-- then we need 7 + 7/4 (8 3/4) circles worth of space across the
-- screen.
Circle_Width : constant Float := Float (Xright - Xleft + 1) / 8.75;
X_Space : constant Float := Float (Xright - Xleft + 1) / 7.0;
-- the horizontal space between circle centers
X_First : constant Integer := Xleft + Integer (0.625 * Circle_Width);
-- the first x coordinate is to the middle of the first circle,
-- which is 1/8 circle size + 1/2 circle size (5/8)
-- Similarly, vertically there will be 6 full intervals, and again
-- assuming an interval is 1/4 as tall as the space for the circle,
-- we get 6 + 6/4 (7 1/2) circles vertically on the screen
Circle_Height : constant Float := Float (Ybottom - Ytop + 1) / 7.5;
Y_Space : constant Float := Float (Ybottom - Ytop + 1) / 6.0;
Y_First : constant Integer := Ytop + Integer (0.625 * Circle_Height);
-- column_breaks holds the x coordinates where the transition from
-- one column to the next occurs
-- That is, column_breaks(1) is the rightmost x coordinate where
-- you can click and still be in column 1
type Column_Breaks_Array_Type is array (1 .. Num_Columns) of Integer;
Column_Breaks : constant Column_Breaks_Array_Type :=
(Integer (1.25 * Circle_Width), Integer (2.5 * Circle_Width), Integer (3.75 * Circle_Width),
Integer (5.00 * Circle_Width), Integer (6.25 * Circle_Width), Integer (7.5 * Circle_Width),
Integer (8.75 * Circle_Width));
----------------------
-- Initialize_Board --
----------------------
-- Initializes board to all none
procedure Initialize_Board (Board : out Board_Array_Type);
procedure Initialize_Board (Board : out Board_Array_Type) is
begin
Board := (others => (others => None));
end Initialize_Board;
------------------------------------------------------------------------
--
-- Name : Place_Disk
-- Description : Determines the row in the given column at which
-- who's disk should be placed (in the lowest empty
-- row, where a lower row has a higher index). Puts
-- who at that row/column in the board, then calls
-- Draw_Position to update the screen.
--
------------------------------------------------------------------------
procedure Place_Disk
(Board : in out Board_Array_Type;
Column : in Integer;
Row : out Integer;
Who : in Player_Kind);
procedure Place_Disk
(Board : in out Board_Array_Type;
Column : in Integer;
Row : out Integer;
Who : in Player_Kind)
is
begin
Row := 1;
-- starting at the top, loop until you find an non-empty row
-- in this column
while (Row <= Num_Rows) and then (Board (Row, Column) = None) loop
Row := Row + 1;
end loop;
-- the new disk will be placed just above the first non-empty row
Row := Row - 1;
-- place the disk
Board (Row, Column) := Who;
end Place_Disk;
---------------
-- Check_Won --
---------------
-- Checks to see if Who won
procedure Check_Won
(Board : in Board_Array_Type;
Who : in Player_Kind;
Won : out Boolean);
procedure Check_Won
(Board : in Board_Array_Type;
Who : in Player_Kind;
Won : out Boolean)
is
begin
-- Set Won to false
Won := False;
-- Loop through all rows
for Row in Board'Range (1) loop
-- Loop through all columns
for Column in Board'Range (2) loop
-- (checking row to the right)
-- If column <= Num_Columns - 3
if (Column <= Num_Columns - 3) then
-- If current location and row, column+1;
-- row, column+2; and
-- row, column+3 belong to who
if (Board (Row, Column) = Who) and (Board (Row, Column + 1) = Who) and
(Board (Row, Column + 2) = Who) and (Board (Row, Column + 3) = Who)
then
-- Set Won to true
Won := True;
end if;
end if;
-- (checking column down)
-- If row <= Num_Rows - 3
if (Row <= Num_Rows - 3) then
-- If current location and row+1, column;
-- row+2, column; and
-- row+3, column belong to who
if (Board (Row, Column) = Who) and (Board (Row + 1, Column) = Who) and
(Board (Row + 2, Column) = Who) and (Board (Row + 3, Column) = Who)
then
-- Set Won to true
Won := True;
end if;
end if;
-- (checking diagonal up to right)
-- If row >= 4 and column <= Num_Columns - 3
if (Row >= 4) and (Column <= Num_Columns - 3) then
-- If current location and row-1, column+1;
-- row-2, column+2;
-- and row-3,column+3 belong to who
if (Board (Row, Column) = Who) and (Board (Row - 1, Column + 1) = Who) and
(Board (Row - 2, Column + 2) = Who) and (Board (Row - 3, Column + 3) = Who)
then
-- Set Won to true
Won := True;
end if;
end if;
-- (checking diagonal down to right)
-- If row <= Num_Rows - 3 and column <= Num_Columns - 3
if (Row <= Num_Rows - 3) and (Column <= Num_Columns - 3) then
-- If current location and row+1, column+1;
-- row+2, column+2;
-- and row+3,column+3 belong to who
if (Board (Row, Column) = Who) and (Board (Row + 1, Column + 1) = Who) and
(Board (Row + 2, Column + 2) = Who) and (Board (Row + 3, Column + 3) = Who)
then
-- Set Won to true
Won := True;
end if;
end if;
end loop;
end loop;
end Check_Won;
---------------
-- Check_Tie --
---------------
-- Checks to see if the game has ended in a tie (all columns are full)
procedure Check_Tie
(Board : in Board_Array_Type;
Is_Tie : out Boolean);
procedure Check_Tie
(Board : in Board_Array_Type;
Is_Tie : out Boolean)
is
begin
-- Set Is_Tie to True
Is_Tie := True;
-- If we find any row with top column empty, then
-- it is NOT a tie.
for Index in Board'Range (2) loop
if (Board (1, Index) = None) then
Is_Tie := False;
end if;
end loop;
end Check_Tie;
-------------------
-- Computer_Turn --
-------------------
-- Uses lookahead and live tuple heuristic
procedure Computer_Turn
(Board : in Board_Array_Type;
Column : out Integer);
procedure Computer_Turn
(Board : in Board_Array_Type;
Column : out Integer)
is
Lookahead_Depth : constant Integer := 5;
type Column_Breaks_Array_Type is array (1 .. Num_Columns) of Integer;
type Value_Type is -- need two ties for symmetry
(Illegal, Win_For_User, Tie_For_User, Unknown, Tie_For_Computer, Win_For_Computer);
type Value_Array_Type is array (1 .. Num_Columns) of Value_Type;
--------------------
-- Make_New_Board --
--------------------
procedure Make_New_Board
(New_Board : out Board_Array_Type;
Board : in Board_Array_Type;
Who : Player_Kind;
Column : Integer);
procedure Make_New_Board
(New_Board : out Board_Array_Type;
Board : in Board_Array_Type;
Who : Player_Kind;
Column : Integer)
is
Dummy_Row : Integer;
begin
New_Board := Board;
Place_Disk (New_Board, Column, Dummy_Row, Who);
end Make_New_Board;
----------------------
-- Find_Best_Result --
----------------------
function Find_Best_Result
(Evaluations : in Value_Array_Type;
Who : Player_Kind)
return Value_Type;
function Find_Best_Result
(Evaluations : in Value_Array_Type;
Who : Player_Kind)
return Value_Type
is
Best_Result : Value_Type;
begin
if Who = Computer then
-- find "largest" move
Best_Result := Win_For_User;
for I in Evaluations'Range loop
if Evaluations (I) > Best_Result and Evaluations (I) /= Illegal then
Best_Result := Evaluations (I);
end if;
end loop;
else
-- Who = User, find "smallest" move
Best_Result := Win_For_Computer;
for I in Evaluations'Range loop
if Evaluations (I) < Best_Result and Evaluations (I) /= Illegal then
Best_Result := Evaluations (I);
end if;
end loop;
end if;
return Best_Result;
end Find_Best_Result;
------------------------
-- Weighting_Function --
------------------------
function Weighting_Function
(Arg : in Integer)
return Integer;
function Weighting_Function
(Arg : in Integer)
return Integer
is
begin
return (Arg * Arg * Arg);
-- use cubic for now
end Weighting_Function;
----------------------------
-- Evaluate_Unknown_Board --
----------------------------
function Evaluate_Unknown_Board
(Board : in Board_Array_Type)
return Integer;
function Evaluate_Unknown_Board
(Board : in Board_Array_Type)
return Integer
is
Owner : Player_Kind;
Cell : Player_Kind;
User_Count, Computer_Count, Board_Value : Integer;
Dead : Boolean;
begin
Board_Value := 0;
for Row in Board'Range (1) loop
for Column in Board'Range (2) loop
-- (checking horizontal tuples)
if (Column <= Num_Columns - 3) then
Owner := None;
User_Count := 0;
Computer_Count := 0;
Dead := False;
for I in 0 .. 3 loop
Cell := Board (Row, Column + I);
if Owner = None and Cell /= None then
Owner := Cell;
end if;
if (Cell = User and Owner = Computer) or (Cell = Computer and Owner = User) then
User_Count := 0;
Computer_Count := 0;
Dead := True;
end if;
if Cell = User and not Dead then
User_Count := User_Count + 1;
elsif Cell = Computer and not Dead then
Computer_Count := Computer_Count + 1;
end if;
end loop;
-- Computer count is positive, User count is negative so
-- that larger values are better for computer
Board_Value := Board_Value + Weighting_Function (Computer_Count) - Weighting_Function (User_Count);
end if;
-- (checking vertical tuples)
if (Row <= Num_Rows - 3) then
Owner := None;
User_Count := 0;
Computer_Count := 0;
Dead := False;
for I in 0 .. 3 loop
Cell := Board (Row + I, Column);
if Owner = None and Cell /= None then
Owner := Cell;
end if;
if (Cell = User and Owner = Computer) or (Cell = Computer and Owner = User) then
User_Count := 0;
Computer_Count := 0;
Dead := True;
end if;
if Cell = User and not Dead then
User_Count := User_Count + 1;
elsif Cell = Computer and not Dead then
Computer_Count := Computer_Count + 1;
end if;
end loop;
Board_Value := Board_Value + Weighting_Function (Computer_Count) - Weighting_Function (User_Count);
end if;
-- (checking diagonal tuples up to right)
if (Row >= Num_Rows / 2 + 1 and Column <= Num_Columns - 3) then
Owner := None;
User_Count := 0;
Computer_Count := 0;
Dead := False;
for I in 0 .. 3 loop
Cell := Board (Row - I, Column + I);
if Owner = None and Cell /= None then
Owner := Cell;
end if;
if (Cell = User and Owner = Computer) or (Cell = Computer and Owner = User) then
User_Count := 0;
Computer_Count := 0;
Dead := True;
end if;
if Cell = User and not Dead then
User_Count := User_Count + 1;
elsif Cell = Computer and not Dead then
Computer_Count := Computer_Count + 1;
end if;
end loop;
Board_Value := Board_Value + Weighting_Function (Computer_Count) - Weighting_Function (User_Count);
end if;
-- (checking diagonal tuples down to right)
if (Row <= Num_Rows - 3) and (Column <= Num_Columns - 3) then
Owner := None;
User_Count := 0;
Computer_Count := 0;
Dead := False;
for I in 0 .. 3 loop
Cell := Board (Row + I, Column + I);
if Owner = None and Cell /= None then
Owner := Cell;
end if;
if (Cell = User and Owner = Computer) or (Cell = Computer and Owner = User) then
User_Count := 0;
Computer_Count := 0;
Dead := True;
end if;
if Cell = User and not Dead then
User_Count := User_Count + 1;
elsif Cell = Computer and not Dead then
Computer_Count := Computer_Count + 1;
end if;
end loop;
Board_Value := Board_Value + Weighting_Function (Computer_Count) - Weighting_Function (User_Count);
end if;
end loop;
end loop;
return Board_Value;
end Evaluate_Unknown_Board;
--------------------
-- Evaluate_Board --
--------------------
function Evaluate_Board
(Board : in Board_Array_Type;
Who_Just_Moved : in Player_Kind;
Current_Depth : in Integer)
return Value_Type;
function Evaluate_Board
(Board : in Board_Array_Type;
Who_Just_Moved : in Player_Kind;
Current_Depth : in Integer)
return Value_Type
is
Computer_Won, User_Won, Is_Tie : Boolean;
Value : Value_Type;
Who_Moves_Next : Player_Kind;
New_Board : Board_Array_Type;
Evaluations : Value_Array_Type;
begin
Check_Won (Board => Board, Who => Computer, Won => Computer_Won);
if not Computer_Won then
Check_Won (Board => Board, Who => User, Won => User_Won);
if not User_Won then
Check_Tie (Board, Is_Tie);
end if;
end if;
if Computer_Won then
Value := Win_For_Computer;
elsif User_Won then
Value := Win_For_User;
elsif Is_Tie and Who_Just_Moved = User then
Value := Tie_For_User;
elsif Is_Tie and Who_Just_Moved = Computer then
Value := Tie_For_Computer;
elsif Current_Depth = 1 then
Value := Unknown;
else
-- Not a terminal node or end of lookahead, so recurse
if Who_Just_Moved = Computer then
Who_Moves_Next := User;
else
Who_Moves_Next := Computer;
end if;
for Col in Evaluations'Range loop
Evaluations (Col) := Illegal;
end loop;
for Col in Board'Range (2) loop
if Board (1, Col) = None then
Make_New_Board (New_Board, Board, Who_Moves_Next, Col);
Evaluations (Col) := Evaluate_Board (New_Board, Who_Moves_Next, Current_Depth - 1);
-- a/b pruning
exit when Evaluations (Col) = Win_For_Computer and Who_Moves_Next = Computer;
exit when Evaluations (Col) = Win_For_User and Who_Moves_Next = User;
else
Evaluations (Col) := Illegal;
end if;
end loop;
Value := Find_Best_Result (Evaluations, Who_Moves_Next);
end if;
return Value;
end Evaluate_Board;
--------------------
-- Find_Best_Move --
--------------------
function Find_Best_Move
(Evaluations : in Value_Array_Type;
Who : Player_Kind)
return Integer;
function Find_Best_Move
(Evaluations : in Value_Array_Type;
Who : Player_Kind)
return Integer
is
Best_Move : Integer;
Best_Result : Value_Type;
begin
if Who = Computer then
-- find "largest" move
Best_Result := Win_For_User;
for I in Evaluations'Range loop
if Evaluations (I) > Best_Result and Evaluations (I) /= Illegal then
Best_Result := Evaluations (I);
Best_Move := I;
end if;
end loop;
else
-- Who = User, find "smallest" move
Best_Result := Win_For_Computer;
for I in Evaluations'Range loop
if Evaluations (I) < Best_Result and Evaluations (I) /= Illegal then
Best_Result := Evaluations (I);
Best_Move := I;
end if;
end loop;
end if;
return Best_Move;
end Find_Best_Move;
-----------------------
-- Find_All_Unknowns --
-----------------------
procedure Find_All_Unknowns
(Evaluations : in Value_Array_Type;
Moves : out Column_Breaks_Array_Type;
Count : out Integer);
procedure Find_All_Unknowns
(Evaluations : in Value_Array_Type;
Moves : out Column_Breaks_Array_Type;
Count : out Integer)
is
begin
Count := 0;
for I in Evaluations'Range loop
if Evaluations (I) = Unknown then
Count := Count + 1;
Moves (Count) := I;
end if;
end loop;
end Find_All_Unknowns;
-- variables and body for "Computer_Turn"
New_Board : Board_Array_Type;
Evaluations : Value_Array_Type;
Moves_To_Unknown : Column_Breaks_Array_Type;
Count_Unknowns : Integer;
Value, Max_Value, Best_Move : Integer;
begin
Evaluations := (others => Illegal);
for Col in Board'Range (2) loop
if Board (1, Col) = None then
Make_New_Board (New_Board, Board, Computer, Col);
Evaluations (Col) := Evaluate_Board (New_Board, Computer, Lookahead_Depth);
-- a/b pruning
exit when Evaluations (Col) = Win_For_Computer;
else
Evaluations (Col) := Illegal;
end if;
end loop;
Column := Find_Best_Move (Evaluations, Computer);
-- Check if trapped, if so take best move at shallower depth
-- and hope for a mistake
if Evaluations (Column) = Win_For_User then
for Col in Board'Range (2) loop
if Board (1, Col) = None then
Make_New_Board (New_Board, Board, Computer, Col);
Evaluations (Col) := Evaluate_Board (New_Board, Computer, 2);
else
Evaluations (Col) := Illegal;
end if;
end loop;
Column := Find_Best_Move (Evaluations, Computer);
elsif Evaluations (Column) = Unknown then
-- If choosing from multiple unknown boards, apply heuristics. This
-- is where most of the strategy is.
Find_All_Unknowns (Evaluations, Moves_To_Unknown, Count_Unknowns);
Max_Value := -1_000;
for I in 1 .. Count_Unknowns loop
Make_New_Board (New_Board, Board, Computer, Moves_To_Unknown (I));
Value := Evaluate_Unknown_Board (New_Board);
if Value > Max_Value then
Max_Value := Value;
Best_Move := Moves_To_Unknown (I);
end if;
end loop;
-- unknown boards
Column := Best_Move;
end if;
-- picking from multiple unknown boards
exception
when others =>
Column := 1;
loop
exit when Board (1, Column) = None;
Column := Column + 1;
end loop;
end Computer_Turn;
----------
-- Init --
----------
procedure Repaint (This : access Typ);
procedure Init (This : access Typ) is
-- procedure Adainit;
-- pragma Import (Ada, Adainit, "ada_connectfour.adainit");
begin
-- Adainit;
-- The above call is needed for elaboration
-- Addmouselistener (This, This.I_Mouselistener);
This.The_Canvas.Create (This.all, 500, 350);
This.On_Mouse_Down_Handler (mousePressed'Access);
This.On_Mouse_Up_Handler (mouseReleased'Access);
Initialize_Board (Board => This.Board);
This.Computer_Won := False;
This.User_Won := False;
This.Tie := False;
This.Ignore_Turn := False;
This.User_Turn := True;
Gnoga.Gui.Window.Browser_Status_Bar (This.Main_Window.all, Format_CPYR (This.Locale));
Repaint (This);
This.Put_Line (Format_DEVP (This.Locale));
This.Put_Line (Format_INFO (This.Locale));
This.Put_Line (Format_ADPT (This.Locale));
end Init;
-----------
-- Paint --
-----------
procedure Paint
(This : access Typ;
G1 : access Gnoga.Gui.Element.Canvas.Context_2D.Context_2D_Type)
is
-- D : access Java.Awt.Dimension.Typ'Class := Getsize (This);
-- Xoff : Int := D.Width / 3;
-- Yoff : Int := D.Height / 3;
--------------------------------------------------------------
-- procedure Display_Text
--
-- display text in black at the given coordinates
--------------------------------------------------------------
procedure Display_Text
(X : in Integer;
Y : in Integer;
Text : in String);
procedure Display_Text
(X : in Integer;
Y : in Integer;
Text : in String)
is
begin
-- Setcolor(G1,Java.Awt.Color.Black);
G1.Stroke_Color (Gnoga.Types.Colors.Black);
G1.Fill_Color (Gnoga.Types.Colors.Black);
-- Drawstring(G1,+Text,X,Y);
G1.Stroke_Text (Text, X, Y);
end Display_Text;
--------------------------------------------------------------
-- procedure Draw_Line
--
-- display line in given color at the given coordinates
--------------------------------------------------------------
procedure Draw_Line
(X1 : in Integer;
Y1 : in Integer;
X2 : in Integer;
Y2 : in Integer;
Hue : Gnoga.Types.Colors.Color_Enumeration);
procedure Draw_Line
(X1 : in Integer;
Y1 : in Integer;
X2 : in Integer;
Y2 : in Integer;
Hue : Gnoga.Types.Colors.Color_Enumeration)
is
begin
-- Setcolor(G1,Hue);
G1.Stroke_Color (Hue);
-- Drawline(G1,X1,Y1,X2,Y2);
G1.Begin_Path;
G1.Move_To (X1, Y1);
G1.Line_To (X2, Y2);
G1.Stroke;
end Draw_Line;
--------------------------------------------------------------
-- procedure Draw_Circle
--
-- Draw a circle of the given color with given center
-- and radius. Will be filled based on filled parameter
--------------------------------------------------------------
procedure Draw_Circle
(X : in Integer;
Y : in Integer;
Radius : in Integer;
Hue : Gnoga.Types.Colors.Color_Enumeration;
Filled : in Boolean);
procedure Draw_Circle
(X : in Integer;
Y : in Integer;
Radius : in Integer;
Hue : Gnoga.Types.Colors.Color_Enumeration;
Filled : in Boolean)
is
begin
-- Setcolor(G1,Hue);
G1.Stroke_Color (Hue);
G1.Begin_Path;
if Filled then
G1.Fill_Color (Hue);
-- Filloval(G1,X-Radius,Y-Radius,2*Radius,2*Radius);
G1.Arc_Degrees (X, Y, Radius, 0.0, 360.0);
G1.Fill;
else
-- Drawoval(G1,X-Radius,Y-Radius,2*Radius,2*Radius);
G1.Arc_Degrees (X, Y, Radius, 0.0, 360.0);
end if;
G1.Stroke;
end Draw_Circle;
--------------------------------------------------------------
-- procedure Draw_Box
--
-- display rectangle in given color at the given coordinates
-- will be filled (vs. outline only) based on filled parameter
--------------------------------------------------------------
procedure Draw_Box
(X1 : in Integer;
Y1 : in Integer;
X2 : in Integer;
Y2 : in Integer;
Hue : Gnoga.Types.Colors.Color_Enumeration;
Filled : in Boolean);
procedure Draw_Box
(X1 : in Integer;
Y1 : in Integer;
X2 : in Integer;
Y2 : in Integer;
Hue : Gnoga.Types.Colors.Color_Enumeration;
Filled : in Boolean)
is
begin
-- Setcolor(G1,Hue);
G1.Stroke_Color (Hue);
if Filled then
G1.Fill_Color (Hue);
-- Fillrect(G1,X1,Y1,X2-X1,Y2-Y1);
G1.Fill_Rectangle ((X1, Y1, X2 - X1, Y2 - Y1));
else
-- Drawrect(G1,X1,Y1,X2-X1,Y2-Y1);
G1.Rectangle ((X1, Y1, X2 - X1, Y2 - Y1));
end if;
end Draw_Box;
------------------------------------------------------------------------
--
-- Name : Draw_Position
-- Description : Draws a disk with the appropriate color for the
-- given player at the given row and column
--
------------------------------------------------------------------------
procedure Draw_Position
(Who : in Player_Kind;
Row : in Integer;
Column : in Integer);
procedure Draw_Position
(Who : in Player_Kind;
Row : in Integer;
Column : in Integer)
is
-- for later
Color : Gnoga.Types.Colors.Color_Enumeration;
-- color of disk
Circle_Radius : Integer;
-- radius of disk
begin
-- Determine radius based on minimum of possible height/width
if Circle_Width < Circle_Height then
Circle_Radius := Integer (Circle_Width * 0.5);
else
Circle_Radius := Integer (Circle_Height * 0.5);
end if;
-- Determine color of disk
case Who is
when None =>
Color := Gnoga.Types.Colors.White;
when Computer =>
Color := Gnoga.Types.Colors.Red;
when User =>
Color := Gnoga.Types.Colors.Blue;
end case;
Draw_Circle
(X => X_First + Integer (Float (Column - 1) * X_Space), Y => Y_First + Integer (Float (Row - 1) * Y_Space),
Radius => Circle_Radius, Hue => Color, Filled => True);
end Draw_Position;
------------------------------------------------------------------------
--
-- Name : Print_Board
-- Description : Prints the board for the start of the game. This
-- procedure should NOT be called repeatedly. Rather,
-- this procedure is called once to draw the game board,
-- then draw_position is used to add player's disks as
-- the game progresses.
--
------------------------------------------------------------------------
procedure Print_Board (Board : in Board_Array_Type);
procedure Print_Board (Board : in Board_Array_Type) is
begin
-- change the screen color if the game is over.
if This.User_Won or This.Tie then
Draw_Box (X1 => 0, Y1 => 0, X2 => 499, Y2 => 299, Hue => Gnoga.Types.Colors.Pink, Filled => True);
elsif This.Computer_Won then
Draw_Box (X1 => 0, Y1 => 0, X2 => 499, Y2 => 299, Hue => Gnoga.Types.Colors.Gray, Filled => True);
else
Draw_Box (X1 => 0, Y1 => 0, X2 => 499, Y2 => 299, Hue => Gnoga.Types.Colors.Light_Gray, Filled => True);
end if;
-- Print column numbers
for Column in 1 .. Num_Columns loop
Display_Text
(X => X_First + Integer (Float (Column - 1) * X_Space) - Title_Offset, Y => Title_Height,
Text => From_ASCII (Character'Val (Column + 48)));
-- Draw vertical line between columns
if Column < Num_Columns then
Draw_Line
(X1 => Column_Breaks (Column), Y1 => Ytop, X2 => Column_Breaks (Column), Y2 => Ybottom,
Hue => Gnoga.Types.Colors.Black);
end if;
for Row in 1 .. Num_Rows loop
Draw_Position (Who => Board (Row, Column), Row => Row, Column => Column);
end loop;
end loop;
-- Print message if the game is over
if This.Computer_Won then
Display_Text (X => 0, Y => 285, Text => Format_IWIN (This.Locale));
elsif This.User_Won then
Display_Text (X => 0, Y => 285, Text => Format_YWIN (This.Locale));
elsif This.Tie then
Display_Text (X => 0, Y => 285, Text => Format_TIEG (This.Locale));
end if;
end Print_Board;
begin
Print_Board (This.Board);
end Paint;
-------------------------------------
-- procedure Update
--
-- uses an off screen image to double
-- buffer, thus smoothing drawing.
-------------------------------------
-- procedure Update (
-- This : access Typ;
-- G : access Java.Awt.Graphics.Typ'Class ) is
-- Gr : access Java.Awt.Graphics.Typ'Class;
-- Ignore : Java.Boolean;
-- begin
-- -- need to allocate Off_Screen_Buffer only once
-- if Off_Screen_Buffer = null then
-- Off_Screen_Buffer := CreateImage(This,500,300);
-- end if;
--
-- -- draw into the offscreen buffer
-- Gr := Java.Awt.Image.GetGraphics(Off_Screen_Buffer);
-- Paint (This, Gr);
--
-- -- copy offscreen buffer onto applet window
-- Ignore := Java.Awt.Graphics.DrawImage(
-- G,
-- Off_Screen_Buffer,
-- 0,
-- 0,
-- This.I_ImageObserver);
-- end Update;
-------------
-- Repaint --
-------------
procedure Repaint (This : access Typ) is
Context : aliased Gnoga.Gui.Element.Canvas.Context_2D.Context_2D_Type;
begin
Context.Get_Drawing_Context_2D (This.The_Canvas);
Paint (This, Context'Access);
end Repaint;
-------------------
-- GetAppletInfo --
-------------------
function GetAppletInfo
(This : access Typ)
return String
is
begin
return Format_INFO (This.Locale);
end GetAppletInfo;
-------------------
-- mouseReleased --
-------------------
procedure mouseReleased
(This : in out Base_Type'Class;
E : in Mouse_Event_Record)
is
pragma Unreferenced (E);
-- X : Integer := E.X;
-- Y : Integer := E.Y;
-- D : access Java.Awt.Dimension.Typ'Class := Getsize (This);
Column, Dummy_Row : Integer;
Self : constant access Typ := Typ (This)'Access;
begin
-- need to do this before checking won, since we use
-- this for user won.
if Self.Ignore_Turn then
return;
end if;
if Self.User_Won or Self.Computer_Won or Self.Tie then
Initialize_Board (Board => Self.Board);
Self.Computer_Won := False;
Self.User_Won := False;
Self.Tie := False;
Self.Ignore_Turn := False;
if Self.User_Turn then
Self.User_Turn := False;
Gnoga.Gui.Window.Browser_Status_Bar (Self.Main_Window.all, Format_IAMT (Self.Locale));
-- Let computer take turn
Computer_Turn (Board => Self.Board, Column => Column);
-- Place computer disk in the column
Place_Disk (Board => Self.Board, Column => Column, Who => Computer, Row => Dummy_Row);
else
Self.User_Turn := True;
end if;
Repaint (Self);
Gnoga.Gui.Window.Browser_Status_Bar (Self.Main_Window.all, Format_CPYR (Self.Locale));
return;
end if;
Gnoga.Gui.Window.Browser_Status_Bar (Self.Main_Window.all, Format_IAMT (Self.Locale));
-- Let computer take turn
Computer_Turn (Board => Self.Board, Column => Column);
-- Place computer disk in the column
Place_Disk (Board => Self.Board, Column => Column, Who => Computer, Row => Dummy_Row);
-- Check if computer won
Check_Won (Board => Self.Board, Who => Computer, Won => Self.Computer_Won);
-- Check for a Tie
Check_Tie (Board => Self.Board, Is_Tie => Self.Tie);
Repaint (Self);
Gnoga.Gui.Window.Browser_Status_Bar (Self.Main_Window.all, Format_CPYR (Self.Locale));
end mouseReleased;
------------------
-- mousePressed --
------------------
procedure mousePressed
(This : in out Base_Type'Class;
E : in Mouse_Event_Record)
is
X : constant Integer := E.X;
-- Y : Integer := E.Y;
-- D : access Java.Awt.Dimension.Typ'Class := Getsize (This);
Column, Dummy_Row : Integer;
Self : constant access Typ := Typ (This)'Access;
begin
-- don't place disk if game over
if Self.User_Won or Self.Computer_Won or Self.Tie then
Self.Ignore_Turn := False;
return;
end if;
-- look to see if this is a valid click location
-- if not, just ignore this click.
Column := -1;
for I in Self.Board'Range (2) loop
if X <= Column_Breaks (I) then
if Self.Board (1, I) = None then
Column := I;
end if;
exit;
end if;
end loop;
if Column <= 0 then
Self.Ignore_Turn := True;
return;
else
Self.Ignore_Turn := False;
end if;
-- Place user disk in the column
Place_Disk (Board => Self.Board, Column => Column, Who => User, Row => Dummy_Row);
-- Check if user won
Check_Won (Board => Self.Board, Who => User, Won => Self.User_Won);
Check_Tie (Board => Self.Board, Is_Tie => Self.Tie);
if Self.User_Won or Self.Tie then
Self.Ignore_Turn := True;
else
Gnoga.Gui.Window.Browser_Status_Bar (Self.Main_Window.all, Format_IAMT (Self.Locale));
end if;
Repaint (Self);
end mousePressed;
-- The functions below do nothing, but are required to override the ones
-- defined in the interface we are implementing (when they abstract).
-- Otherwise, the JVM would complain.
------------------
-- mouseClicked --
------------------
-- procedure Mouseclicked (
-- This : access Typ;
-- P1 : access Java.Awt.Event.Mouseevent.Typ'Class ) is
-- begin
-- null;
-- end Mouseclicked;
------------------
-- mouseEntered --
------------------
-- procedure Mouseentered (
-- This : access Typ;
-- P1 : access Java.Awt.Event.Mouseevent.Typ'Class ) is
-- begin
-- null;
-- end Mouseentered;
-----------------
-- mouseExited --
-----------------
-- procedure Mouseexited (
-- This : access Typ;
-- P1 : access Java.Awt.Event.Mouseevent.Typ'Class ) is
-- begin
-- null;
-- end Mouseexited;
end ConnectFour;
connectfour_messages.ads
-- -*- coding: utf-8 -*-
--
-- Ada specification generated by ZBMCompile, V1.4.0 (r3199).
-- This is a generated file and should not be edited.
--
with ZanyBlue.Text.Catalogs;
with ZanyBlue.Text.Formatting;
with UXStrings;
package connectfour_messages is
use UXStrings;
subtype String is UXString;
-- Since the body calls the Initialize procedure, this package need
-- only be with'ed. Suppress any compiler warnings about an unused
-- with'ed package.
pragma Warnings (Off, connectfour_messages);
function Standard_Catalog return ZanyBlue.Text.Catalogs.Catalog_Type
renames ZanyBlue.Text.Formatting.Standard_Catalog;
function Facility (Index : Positive) return String;
-- The name of the Index'th Facility item compiled.
-- This routine is normally only used by generated accessor code.
function Facility_Count return Natural;
-- Numnber of Facility items compiled.
-- This routine is normally only used by generated accessor code.
function Key (Index : Positive) return String;
-- The name of the Index'th Key item compiled.
-- This routine is normally only used by generated accessor code.
function Key_Count return Natural;
-- Numnber of Key items compiled.
-- This routine is normally only used by generated accessor code.
procedure Initialize (
Catalog : ZanyBlue.Text.Catalogs.Catalog_Type := Standard_Catalog);
-- The catalog initialization routine: load the compiled messages into
-- a catalog.
end connectfour_messages;
connectfour_messages.adb
-- -*- coding: utf-8 -*-
--
-- Ada implementation generated by ZBMCompile, V1.4.0 (r3199).
-- This is a generated file and should not be edited.
--
package body connectfour_messages is
package ZT renames ZanyBlue.Text;
package ZTC renames ZanyBlue.Text.Catalogs;
subtype Z is ZTC.ZBMCompile_Definition;
Facility_1 : aliased constant String := ""
& "connectfour"
& "";
Facilities : constant ZT.Constant_String_List (1 .. 1) := (
1 => Facility_1'Access);
Key_1 : aliased constant String := ""
& "ADPT"
& "";
Key_2 : aliased constant String := ""
& "APPE"
& "";
Key_3 : aliased constant String := ""
& "CPYR"
& "";
Key_4 : aliased constant String := ""
& "DEVP"
& "";
Key_5 : aliased constant String := ""
& "IAMT"
& "";
Key_6 : aliased constant String := ""
& "INFO"
& "";
Key_7 : aliased constant String := ""
& "IWIN"
& "";
Key_8 : aliased constant String := ""
& "TIEG"
& "";
Key_9 : aliased constant String := ""
& "YWIN"
& "";
Key_10 : aliased constant String := ""
& "TITL"
& "";
Keys : constant ZT.Constant_String_List (1 .. 10) := (
Key_1'Access,
Key_2'Access,
Key_3'Access,
Key_4'Access,
Key_5'Access,
Key_6'Access,
Key_7'Access,
Key_8'Access,
Key_9'Access,
Key_10'Access);
Locale_1 : aliased constant String := ""
& "";
Locale_2 : aliased constant String := ""
& "fr"
& "";
Locales : constant ZT.Constant_String_List (1 .. 2) := (
Locale_1'Access,
Locale_2'Access);
Pool_Data_1 : aliased constant String := ""
& "Adapted for GNOGA by Pascal Pignard (20150613).Application "
& "ended.Connect Four (TM) by Barry Fagin and Martin CarlisleD"
& "eveloped by Barry Fagin and Martin Carlisle, US Air Force A"
& "cademy.I am thinking...This Connect Four (TM) game was init"
& "ially coded in Ada 2005 and compiled with the JVM-GNAT comp"
& "iler.I win! - Press left mouse buttonTie Game! - Press Left"
& " Mouse ButtonYou win! - Press left mouse buttonAdapté pour "
& "GNOGA par Pascal Pignard (20150613).Application terminée.Pu"
& "issance 4 (TM) - Connect Four (TM) par Barry Fagin et Marti"
& "n CarlisleDéveloppé par Barry Fagin et Martin Carlisle, US "
& "Air Force Academy.Je réfléchis..."
& Unicode_Character'Val (16#000A#)
& "Ce jeu de Puissance 4 (TM) a été codé initialement en Ada 2"
& "005 et compilé avec le compilateur JVM-GNAT.J''ai gagné ! -"
& " Appuyez sur le bouton gauche de la sourisPartie nulle ! - "
& "Appuyez sur le bouton gauche de la sourisVous avez gagné ! "
& "- Appuyez sur le bouton gauche de la souris"
& "";
Pool : constant ZT.Static_Message_Pool_Type := Pool_Data_1'Access;
Messages : constant ZTC.ZBMCompile_List (1 .. 20) := (
Z'(First => 471, Last => 486,
Facility_Index => 1, Key_Index => 10,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Puissance 4 (TM)
Z'(First => 542, Last => 608,
Facility_Index => 1, Key_Index => 4,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Développé par Barry Fagin et Martin Carlisle, US Air Fo⤶
-- ↦rce Academy.
Z'(First => 66, Last => 82,
Facility_Index => 1, Key_Index => 10,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦Connect Four (TM)
Z'(First => 843, Last => 903,
Facility_Index => 1, Key_Index => 9,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Vous avez gagné ! - Appuyez sur le bouton gauche de la ⤶
-- ↦souris
Z'(First => 368, Last => 401,
Facility_Index => 1, Key_Index => 9,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦You win! - Press left mouse button
Z'(First => 333, Last => 367,
Facility_Index => 1, Key_Index => 8,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦Tie Game! - Press Left Mouse Button
Z'(First => 785, Last => 842,
Facility_Index => 1, Key_Index => 8,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Partie nulle ! - Appuyez sur le bouton gauche de la sou⤶
-- ↦ris
Z'(First => 450, Last => 470,
Facility_Index => 1, Key_Index => 2,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Application terminée.
Z'(First => 66, Last => 117,
Facility_Index => 1, Key_Index => 3,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦Connect Four (TM) by Barry Fagin and Martin Carlisle
Z'(First => 48, Last => 65,
Facility_Index => 1, Key_Index => 2,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦Application ended.
Z'(First => 471, Last => 541,
Facility_Index => 1, Key_Index => 3,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Puissance 4 (TM) - Connect Four (TM) par Barry Fagin et⤶
-- ↦ Martin Carlisle
Z'(First => 402, Last => 449,
Facility_Index => 1, Key_Index => 1,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Adapté pour GNOGA par Pascal Pignard (20150613).
Z'(First => 1, Last => 47,
Facility_Index => 1, Key_Index => 1,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦Adapted for GNOGA by Pascal Pignard (20150613).
Z'(First => 625, Last => 727,
Facility_Index => 1, Key_Index => 6,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Ce jeu de Puissance 4 (TM) a été codé initialement en A⤶
-- ↦da 2005 et compilé avec le compilateur JVM-GNAT.
Z'(First => 301, Last => 332,
Facility_Index => 1, Key_Index => 7,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦I win! - Press left mouse button
Z'(First => 201, Last => 300,
Facility_Index => 1, Key_Index => 6,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦This Connect Four (TM) game was initially coded in Ada ⤶
-- ↦2005 and compiled with the JVM-GNAT compiler.
Z'(First => 728, Last => 784,
Facility_Index => 1, Key_Index => 7,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦J''ai gagné ! - Appuyez sur le bouton gauche de la sour⤶
-- ↦is
Z'(First => 609, Last => 624,
Facility_Index => 1, Key_Index => 5,
Locale_Index => 2, Source_Locale_Index => 2),
-- ↦Je réfléchis...⏎
Z'(First => 185, Last => 200,
Facility_Index => 1, Key_Index => 5,
Locale_Index => 1, Source_Locale_Index => 1),
-- ↦I am thinking...
Z'(First => 118, Last => 184,
Facility_Index => 1, Key_Index => 4,
Locale_Index => 1, Source_Locale_Index => 1));
-- ↦Developed by Barry Fagin and Martin Carlisle, US Air Fo⤶
-- ↦rce Academy.
---------------
--- Facility --
---------------
function Facility (Index : Positive) return String is
begin
return Facilities (Index).all;
end Facility;
---------------------
--- Facility_Count --
---------------------
function Facility_Count return Natural is
begin
return Facilities'Length;
end Facility_Count;
----------------
-- Initialize --
----------------
procedure Initialize (Catalog : ZTC.Catalog_Type := Standard_Catalog) is
begin
ZTC.Initialize (Catalog, Messages, Pool, Facilities, Keys, Locales,
"connectfour_messages",
Pool_Data_1.Length, 903);
end Initialize;
----------
--- Key --
----------
function Key (Index : Positive) return String is
begin
return Keys (Index).all;
end Key;
----------------
--- Key_Count --
----------------
function Key_Count return Natural is
begin
return Keys'Length;
end Key_Count;
begin -- connectfour_messages
Initialize;
end connectfour_messages;
connectfour_messages-connectfour_strings.ads
-- -*- coding: utf-8 -*-
--
-- Ada specification generated by ZBMCompile, V1.4.0 (r3199).
-- This is a generated file and should not be edited.
--
with ZanyBlue.Text.Catalogs;
with ZanyBlue.Text.Locales;
package connectfour_messages.connectfour_Strings is
use ZanyBlue.Text.Catalogs;
use ZanyBlue.Text.Locales;
function Format_ADPT (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦Adapted for GNOGA by Pascal Pignard (20150613).
function Format_APPE (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦Application ended.
function Format_CPYR (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦Connect Four (TM) by Barry Fagin and Martin Carlisle
function Format_DEVP (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦Developed by Barry Fagin and Martin Carlisle, US Air Fo⤶
-- ↦rce Academy.
function Format_IAMT (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦I am thinking...
function Format_INFO (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦This Connect Four (TM) game was initially coded in Ada ⤶
-- ↦2005 and compiled with the JVM-GNAT compiler.
function Format_IWIN (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦I win! - Press left mouse button
function Format_TIEG (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦Tie Game! - Press Left Mouse Button
function Format_TITL (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦Connect Four (TM)
function Format_YWIN (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String;
-- ↦You win! - Press left mouse button
end connectfour_messages.connectfour_Strings;
connectfour_messages-connectfour_strings.adb
-- -*- coding: utf-8 -*-
--
-- Ada implementation generated by ZBMCompile, V1.4.0 (r3199).
-- This is a generated file and should not be edited.
--
with ZanyBlue.Text.Arguments;
with ZanyBlue.Text.Formatting;
package body connectfour_messages.connectfour_Strings is
use ZanyBlue.Text.Arguments;
use ZanyBlue.Text.Formatting;
-----------------
-- Format_ADPT --
-----------------
function Format_ADPT (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (1),
Empty_Argument_List, Locale, Catalog);
end Format_ADPT;
-----------------
-- Format_APPE --
-----------------
function Format_APPE (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (2),
Empty_Argument_List, Locale, Catalog);
end Format_APPE;
-----------------
-- Format_CPYR --
-----------------
function Format_CPYR (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (3),
Empty_Argument_List, Locale, Catalog);
end Format_CPYR;
-----------------
-- Format_DEVP --
-----------------
function Format_DEVP (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (4),
Empty_Argument_List, Locale, Catalog);
end Format_DEVP;
-----------------
-- Format_IAMT --
-----------------
function Format_IAMT (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (5),
Empty_Argument_List, Locale, Catalog);
end Format_IAMT;
-----------------
-- Format_INFO --
-----------------
function Format_INFO (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (6),
Empty_Argument_List, Locale, Catalog);
end Format_INFO;
-----------------
-- Format_IWIN --
-----------------
function Format_IWIN (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (7),
Empty_Argument_List, Locale, Catalog);
end Format_IWIN;
-----------------
-- Format_TIEG --
-----------------
function Format_TIEG (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (8),
Empty_Argument_List, Locale, Catalog);
end Format_TIEG;
-----------------
-- Format_TITL --
-----------------
function Format_TITL (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (10),
Empty_Argument_List, Locale, Catalog);
end Format_TITL;
-----------------
-- Format_YWIN --
-----------------
function Format_YWIN (
Locale : Locale_Type := Current_Locale;
Catalog : Catalog_Type := Standard_Catalog) return String
is
begin
return Format (Facility (1), Key (9),
Empty_Argument_List, Locale, Catalog);
end Format_YWIN;
end connectfour_messages.connectfour_Strings;
connectfour.properties
#Connect Four en
ADPT=Adapted for GNOGA by Pascal Pignard (20150613).
APPE=Application ended.
CPYR=Connect Four (TM) by Barry Fagin and Martin Carlisle
DEVP=Developed by Barry Fagin and Martin Carlisle, US Air Force Academy.
IAMT=I am thinking...
INFO=This Connect Four (TM) game was initially coded in Ada 2005 and compiled with the JVM-GNAT compiler.
IWIN=I win\! - Press left mouse button
TIEG=Tie Game\! - Press Left Mouse Button
YWIN=You win\! - Press left mouse button
TITL=Connect Four (TM)
connect_four.adb
-------------------------------------------------------------------------------
-- Main procedure for Connect Four web server
-- COPYRIGHT : 20150511 by Pascal Pignard
-- LICENCE : CeCILL V2.1 (http://www.cecill.info)
-- CONTACT : http://blady.pagesperso-orange.fr
-------------------------------------------------------------------------------
with Gnoga.Application;
with Gnoga.Application.Multi_Connect;
with Gnoga.Gui.Window;
with ConnectFour; use ConnectFour;
with connectfour_messages.connectfour_Strings; use connectfour_messages.connectfour_Strings;
with ZanyBlue.Text.Locales;
with Gnoga.Gui.Navigator;
with Gnoga.Server.Connection;
procedure Connect_Four is
use all type Gnoga.String;
procedure On_Connect
(Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
Connection : access Gnoga.Application.Multi_Connect.Connection_Holder_Type);
procedure On_Connect
(Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
Connection : access Gnoga.Application.Multi_Connect.Connection_Holder_Type)
is
Page : aliased Typ;
begin
Page.Create (Main_Window);
Page.Main_Window := Gnoga.Gui.Window.Window_Type (Main_Window)'Unchecked_Access;
Page.Locale :=
ZanyBlue.Text.Locales.Make_Locale_Narrow (Gnoga.Gui.Navigator.Language (Main_Window) & ".ISO8859-1");
Main_Window.Document.Title (Format_TITL (Page.Locale));
Gnoga.Server.Connection.HTML_On_Close (Main_Window.Connection_ID, Format_APPE (Page.Locale));
Init (Page'Access);
Connection.Hold;
end On_Connect;
begin
Gnoga.Application.Multi_Connect.Initialize;
Gnoga.Application.Multi_Connect.On_Connect_Handler (Event => On_Connect'Unrestricted_Access);
Gnoga.Application.Multi_Connect.Message_Loop;
end Connect_Four;
Project file
with "settings.gpr";
with "gnoga.gpr";
with "zanyblue.gpr";
project Connect_Four is
for Object_Dir use Settings.Obj_Dir;
for Exec_Dir use Settings.Exe_Dir;
for Main use ("connect_four.adb");
for Create_Missing_Dirs use Settings'Create_Missing_Dirs;
package Compiler is
for Default_Switches ("Ada") use Settings.Compiler'Default_Switches ("Ada") & "-gnatyN";
end Compiler;
package Binder renames Settings.Binder;
package Linker renames Settings.Linker;
package Pretty_Printer renames Settings.Pretty_Printer;
end Connect_Four;