DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ B T ┃
Length: 37638 (0x9306) Types: TextFile Names: »B«
└─⟦85b835f43⟧ Bits:30000549 8mm tape, Rational 1000, Xlib rev 6.00 └─ ⟦0c20f784e⟧ »DATA« └─⟦1abbe589f⟧ └─⟦306851c02⟧ └─⟦this⟧
with Calendar; with Text_Io; with Button; use Button; with Draw; use Draw; with Main; use Main; with Ran1_Package; use Ran1_Package; with Xlbt_Arithmetic; use Xlbt_Arithmetic; with Xlbt_Basic; use Xlbt_Basic; with Xlbp_Graphics; use Xlbp_Graphics; with Xlbp_Keyboard_Control; use Xlbp_Keyboard_Control; package body Board is ------------------------------------------------------------------------------ -- Dragon - a version of Mah-Jongg for X Windows -- -- Author: Gary E. Barnes March 1989 -- -- Board - Deals with the Mah-Jongg board. Setup and execution. ------------------------------------------------------------------------------ -- 05/30/90 GEB - Translate to Ada ------------------------------------------------------------------------------ Ran_Data : Ran1_Data; --\f procedure Write_Game (File : Text_Io.File_Type) is ------------------------------------------------------------------------------ -- file - Specifies a file open for write -- -- Called to write out the current game context for later rereading. ------------------------------------------------------------------------------ Bp : Board_Position; begin S_Long_Io.Put (File, Score, Width => 0); Text_Io.New_Line (File); for Row in Board_Tiles'Range (1) loop for Col in Board_Tiles'Range (2) loop Bp := Board_Tiles (Row, Col); for I in Bp.Tiles'Range loop S_Long_Io.Put (File, S_Long (Bp.Tiles (0)), Width => 0); Text_Io.Put (File, ' '); end loop; S_Long_Io.Put (File, S_Long (Bp.Level), Width => 0); Text_Io.Put (File, ' '); S_Long_Io.Put (File, S_Long (Bp.X), Width => 0); Text_Io.Put (File, ' '); S_Long_Io.Put (File, S_Long (Bp.Y), Width => 0); Text_Io.New_Line (File); end loop; end loop; end Write_Game; --\f procedure Read_Game (File : Text_Io.File_Type) is ------------------------------------------------------------------------------ -- file - Specifies a file open for reading -- -- Called to read in a new current game context. ------------------------------------------------------------------------------ Bp : Board_Position; begin Click1 := null; Click2 := null; S_Long_Io.Get (File, Score); Text_Io.Skip_Line (File); for Row in Board_Tiles'Range (1) loop for Col in Board_Tiles'Range (2) loop Bp := Board_Tiles (Row, Col); for I in Bp.Tiles'Range loop S_Long_Io.Get (File, S_Long (Bp.Tiles (0)), Width => 0); end loop; Bp.Draw := True; S_Long_Io.Get (File, S_Long (Bp.Level), Width => 0); S_Long_Io.Get (File, S_Long (Bp.X), Width => 0); S_Long_Io.Get (File, S_Long (Bp.Y), Width => 0); Text_Io.Skip_Line (File); end loop; end loop; end Read_Game; --\f procedure Pick_Tile (Avail : in out U_Char_Array; Pick : out U_Char) is ------------------------------------------------------------------------------ -- Avail - Specifies an [NTILES] array of available tiles. Unavailable -- slots contain NO_TILE. -- -- Called to pick a random tile from the Available tiles. ------------------------------------------------------------------------------ T : U_Char; K : S_Long; begin ----Pick a random starting place. K := S_Long (Ran1 (Ran_Data) * Float (S_Long'Last / 2)) rem N_Tiles; ----Search until we find a non-NO_TILE slot. while (Avail (K) = No_Tile) loop K := K + 1; if K = N_Tiles then K := 0; end if; end loop; ----Return the tile we found and zap the slot. T := Avail (K); Avail (K) := No_Tile; Pick := T; end Pick_Tile; --\f procedure Set_Tile_Controls is ------------------------------------------------------------------------------ -- Called whenever the board has been reset or resized. We recalculate all of -- the drawing controls for the tiles. ------------------------------------------------------------------------------ begin ----Now set up the control information for all of the tiles. The special -- tiles are easy. if Board_Tiles (Spec4_Row, Spec4_Col).Level > 0 then Board_Tiles (Spec4_Row, Spec4_Col).X := Board_Tile0_X + 6 * (Tile_Width + 1) + (Tile_Width + 1) / 2 + 4 * Side_X; Board_Tiles (Spec4_Row, Spec4_Col).Y := Board_Tile0_Y + 3 * (Tile_Height + 1) + (Tile_Height + 1) / 2 - 3 * Side_Y; end if; if Board_Tiles (Spec3_Row, Spec3_Col).Level > 0 then Board_Tiles (Spec3_Row, Spec3_Col).X := Board_Tile0_X + 0 * (Tile_Width + 1); Board_Tiles (Spec3_Row, Spec3_Col).Y := Board_Tile0_Y + 3 * (Tile_Height + 1) + (Tile_Height + 1) / 2; end if; if Board_Tiles (Spec2_Row, Spec2_Col).Level > 0 then Board_Tiles (Spec2_Row, Spec2_Col).X := Board_Tile0_X + 13 * (Tile_Width + 1); Board_Tiles (Spec2_Row, Spec2_Col).Y := Board_Tile0_Y + 3 * (Tile_Height + 1) + (Tile_Height + 1) / 2; end if; if Board_Tiles (Spec1_Row, Spec1_Col).Level > 0 then Board_Tiles (Spec1_Row, Spec1_Col).X := Board_Tile0_X + 14 * (Tile_Width + 1); Board_Tiles (Spec1_Row, Spec1_Col).Y := Board_Tile0_Y + 3 * (Tile_Height + 1) + (Tile_Height + 1) / 2; end if; ----Do the more regular tiles. for Row in S_Short range 0 .. 7 loop for Col in reverse S_Short range 1 .. 12 loop declare Bp : Board_Position renames Board_Tiles (Row, Col); begin ----Skip any tiles that don't exist. if Bp.Level /= 0 then ----Set up the face x/y coordinates. Bp.X := Board_Tile0_X + Col * (Tile_Width + 1); Bp.Y := Board_Tile0_Y + Row * (Tile_Height + 1); end if; end; end loop; end loop; end Set_Tile_Controls; --\f procedure Pick1 (Bp : Board_Position; Avail : in out U_Char_Array) is begin Pick_Tile (Avail, Bp.Tiles (0)); Bp.Level := 1; end Pick1; procedure Pick2 (Bp : Board_Position; Avail : in out U_Char_Array) is begin Pick_Tile (Avail, Bp.Tiles (0)); Pick_Tile (Avail, Bp.Tiles (1)); Bp.Level := 2; end Pick2; procedure Pick3 (Bp : Board_Position; Avail : in out U_Char_Array) is begin Pick_Tile (Avail, Bp.Tiles (0)); Pick_Tile (Avail, Bp.Tiles (1)); Pick_Tile (Avail, Bp.Tiles (2)); Bp.Level := 3; end Pick3; procedure Pick4 (Bp : Board_Position; Avail : in out U_Char_Array) is begin Pick_Tile (Avail, Bp.Tiles (0)); Pick_Tile (Avail, Bp.Tiles (1)); Pick_Tile (Avail, Bp.Tiles (2)); Pick_Tile (Avail, Bp.Tiles (3)); Bp.Level := 4; end Pick4; --\f procedure Setup_New_Game is ------------------------------------------------------------------------------ -- Called to generate an all-new game. ------------------------------------------------------------------------------ Avail : U_Char_Array (0 .. N_Tiles - 1); I : S_Long; begin ----Clear the board. for Row in S_Short range 0 .. N_Rows - 1 loop for Col in S_Short range 0 .. N_Cols - 1 loop declare Bp : Board_Position renames Board_Tiles (Row, Col); begin Bp.Tiles (0) := No_Tile; Bp.Tiles (1) := No_Tile; Bp.Tiles (2) := No_Tile; Bp.Tiles (3) := No_Tile; Bp.Level := 0; end; end loop; end loop; ----Mark all tiles as available. I := 0; for Row in S_Short range 0 .. 3 loop Avail (I) := U_Char (Row + 1); I := I + 1; Avail (I) := U_Char (Row + 5); I := I + 1; for Col in S_Short range 8 .. N_Faces - 1 loop Avail (I) := U_Char (1 + Col rem N_Faces); I := I + 1; end loop; end loop; if I /= N_Tiles then Text_Io.Put_Line ("NTILES gak!"); end if; ----Fill in the "odd" tile slots. Pick1 (Board_Tiles (Spec1_Row, Spec1_Col), Avail); Pick1 (Board_Tiles (Spec2_Row, Spec2_Col), Avail); Pick1 (Board_Tiles (Spec3_Row, Spec3_Col), Avail); Pick1 (Board_Tiles (Spec4_Row, Spec4_Col), Avail); for Col in S_Short range 1 .. 12 loop Pick1 (Board_Tiles (0, Col), Avail); Pick1 (Board_Tiles (7, Col), Avail); end loop; for Row in S_Short range 1 .. 6 loop Pick1 (Board_Tiles (Row, 3), Avail); Pick1 (Board_Tiles (Row, 10), Avail); end loop; for Row in S_Short range 2 .. 5 loop Pick1 (Board_Tiles (Row, 2), Avail); Pick1 (Board_Tiles (Row, 11), Avail); end loop; for Row in S_Short range 3 .. 4 loop Pick1 (Board_Tiles (Row, 1), Avail); Pick1 (Board_Tiles (Row, 12), Avail); end loop; ----Now do the next square at level 2. for Col in S_Short range 4 .. 9 loop Pick2 (Board_Tiles (1, Col), Avail); Pick2 (Board_Tiles (6, Col), Avail); end loop; for Row in S_Short range 2 .. 5 loop Pick2 (Board_Tiles (Row, 4), Avail); Pick2 (Board_Tiles (Row, 9), Avail); end loop; ----Now do the next square at level 3. for Col in S_Short range 5 .. 8 loop Pick3 (Board_Tiles (2, Col), Avail); Pick3 (Board_Tiles (5, Col), Avail); end loop; for Row in S_Short range 3 .. 4 loop Pick3 (Board_Tiles (Row, 5), Avail); Pick3 (Board_Tiles (Row, 8), Avail); end loop; ----Now do the final square at level 4. for Row in S_Short range 3 .. 4 loop for Col in S_Short range 6 .. 7 loop Pick4 (Board_Tiles (Row, Col), Avail); end loop; end loop; ----Now set up the control information for all of the tiles. Set_Tile_Controls; Score := N_Tiles; end Setup_New_Game; --\f procedure Restart_Game (Event : X_Button_Press_Event) is ------------------------------------------------------------------------------ -- Called when the RESTART button is pressed. Restart the game. ------------------------------------------------------------------------------ begin ----Reset levels and remove hilites. Click1 := null; Click2 := null; Score := N_Tiles; for Row in S_Short range 0 .. N_Rows - 1 loop for Col in S_Short range 0 .. N_Cols - 1 loop declare Bp : Board_Position renames Board_Tiles (Row, Col); begin if Bp.Tiles (3) /= No_Tile then Bp.Level := 4; elsif Bp.Tiles (2) /= No_Tile then Bp.Level := 3; elsif Bp.Tiles (1) /= No_Tile then Bp.Level := 2; else if Bp.Tiles (0) /= No_Tile then Bp.Level := 1; else Bp.Level := 0; end if; end if; end; end loop; end loop; ----Finish setting up and then redraw everything. Set_Tile_Controls; X_Clear_Area (Dpy, Main.Board, 0, 0, 0, 0, True); end Restart_Game; --\f procedure Set_Tile_Draw (Row : S_Short; Col : S_Short) is ------------------------------------------------------------------------------ -- row - Specifies the row of the tile -- col - Specifies the column of the tile -- -- Called to set the "draw" flag on a tile. We also recursively set the -- draw flag on anyone that needs to be redrawn because we are being redrawn. ------------------------------------------------------------------------------ Bp : Board_Position renames Board_Tiles (Row, Col); begin ---If we don't exist or if we are already being redrawn then stop. if Bp.Level = 0 or else Bp.Draw then return; end if; ----Redraw us. Redraw anyone to our left that has a height greater than ours -- ecause their shadow/tile-face overlaps us. Bp.Draw := True; if Col > 0 and then Board_Tiles (Row, Col - 1).Level > Bp.Level then Set_Tile_Draw (Row, Col - 1); end if; ----Redraw anyone below us that has a level greater than ours because their -- hadow/tile-face overlaps us. if Row < 7 and then Board_Tiles (Row + 1, Col).Level > Bp.Level then Set_Tile_Draw (Row + 1, Col); end if; ----Redraw anyone below-to-the-left of us. if Row < 7 and then Col > 0 and then Board_Tiles (Row + 1, Col - 1).Level > 0 then Set_Tile_Draw (Row + 1, Col - 1); end if; ----Redraw anyone above-to-the-left of us that has a level greater than ours -- ecause their tile-face overlaps our tile-edge. if Row > 0 and then Col > 0 and then Board_Tiles (Row - 1, Col - 1).Level /= Bp.Level then Set_Tile_Draw (Row - 1, Col - 1); end if; ----If we are certain specific tiles then we may need to set specific other -- tiles. if Row = 3 or else Row = 4 then if Col = 6 or else Col = 7 then Set_Tile_Draw (Spec4_Row, Spec4_Col); elsif Col = 1 then Set_Tile_Draw (Spec3_Row, Spec3_Col); end if; end if; end Set_Tile_Draw; --\f procedure Remove_Tile (Bp : Board_Position; Row : S_Short; Col : S_Short) is ------------------------------------------------------------------------------ -- Called to remove the top tile of the indicated Board_Position. ------------------------------------------------------------------------------ begin ----If the tile just went away then clear the area and allow the window -- ackground to shine through. if Bp.Level = 1 then if (Tile_Control and Shadow) /= 0 then X_Clear_Area (Dpy, Main.Board, Bp.X, Bp.Y - Side_Y - Shadow_Y, U_Short (Tile_Width + Side_X + 2 + Shadow_X), U_Short (Tile_Height + Side_Y + 2 + Shadow_Y), False); else X_Clear_Area (Dpy, Main.Board, Bp.X, Bp.Y - Side_Y, U_Short (Tile_Width + Side_X + 2), U_Short (Tile_Height + Side_Y + 2), False); end if; else declare Sidex : S_Short := Side_X * Bp.Level; Sidey : S_Short := Side_Y * Bp.Level; begin if (Tile_Control and Shadow) /= 0 then X_Clear_Area (Dpy, Main.Board, Bp.X + Sidex, Bp.Y - Sidey - Shadow_Y, U_Short (Tile_Width + 2 + Shadow_X), U_Short (Tile_Height + 2 + Shadow_Y), False); else X_Clear_Area (Dpy, Main.Board, Bp.X + Sidex, Bp.Y - Sidey, U_Short (Tile_Width + 2), U_Short (Tile_Height + 2), False); end if; Set_Tile_Draw (Row, Col); end; end if; Bp.Level := Bp.Level - 1; ----Schedule the surrounding tiles for redrawing. if Col = Spec1_Col then if Row = Spec4_Row then Set_Tile_Draw (3, 6); Set_Tile_Draw (3, 7); Set_Tile_Draw (4, 6); Set_Tile_Draw (4, 7); return; elsif Row = Spec3_Row then Set_Tile_Draw (3, 1); Set_Tile_Draw (4, 1); return; elsif Row = Spec2_Row then Set_Tile_Draw (Spec1_Row, Spec1_Col); Set_Tile_Draw (3, 12); Set_Tile_Draw (4, 12); return; else Set_Tile_Draw (Spec2_Row, Spec2_Col); Set_Tile_Draw (3, 12); Set_Tile_Draw (4, 12); return; end if; end if; if Col = 1 and then (Row = 3 or else Row = 4) then Set_Tile_Draw (Spec3_Row, Spec3_Col); end if; if Col = 12 and then (Row = 3 or else Row = 4) then Set_Tile_Draw (Spec2_Row, Spec2_Col); end if; if Row > 0 then Set_Tile_Draw (Row - 1, Col + 1); Set_Tile_Draw (Row - 1, Col); if Col > 0 and then Board_Tiles (Row - 1, Col).Level = 0 then Set_Tile_Draw (Row - 1, Col - 1); end if; end if; Set_Tile_Draw (Row, Col + 1); if Col > 0 then Set_Tile_Draw (Row, Col - 1); end if; if Row < 7 then Set_Tile_Draw (Row + 1, Col); if Col > 0 then Set_Tile_Draw (Row + 1, Col - 1); end if; end if; end Remove_Tile; --\f procedure Touch_Tile (Bp : Board_Position; Row : S_Short; Col : S_Short; Event : X_Button_Press_Event) is ------------------------------------------------------------------------------ -- Called when we click on a specific tile. We decide what to do. For a -- single click we hilite the tile unless we already have two tiles hilited. -- For a "double" click with two tiles hilited we will remove both of the -- tiles. ------------------------------------------------------------------------------ begin ----If there is no Click1 then this guy becomes it. if Click1 = null then Click1 := Bp; Click1_Row := Row; Click1_Col := Col; Hilite_Tile (Row, Col); return; end if; ----If there is no Click2 then this guy becomes it unless he is already Click1. if Click1 /= Bp then if Click2_Row = Row and then Click2_Col = Col and then Click2_Time + Dragon_Resources.Double_Click >= Event.Button.Time then Click2 := Bp; end if; if Click2 = null then Click2 := Bp; Click2_Row := Row; Click2_Col := Col; Click2_Time := Event.Button.Time; Hilite_Tile (Row, Col); return; end if; ----If this guy is not one Click1 and not Click2 then we have an error. if Click2 /= Bp then X_Bell (Dpy, 0); return; end if; end if; ----If he double-clicks then remove both tiles. if Click2 /= null and then Click2_Time + Dragon_Resources.Double_Click >= Event.Button.Time then One_Button_Hint := False; Remove_Tile (Click1, Click1_Row, Click1_Col); Click1 := null; Remove_Tile (Click2, Click2_Row, Click2_Col); Click2 := null; Score := Score - 2; Draw_All_Tiles; return; end if; ----2nd click on any tile means turn-it-off. if Click1 = Bp then declare S : S_Short; begin Hilite_Tile (Click1_Row, Click1_Col); Click1 := Click2; S := Click1_Row; Click1_Row := Click2_Row; Click2_Row := S; S := Click1_Col; Click1_Col := Click2_Col; Click2_Col := S; Click2 := null; end; else Click2 := null; Hilite_Tile (Click2_Row, Click2_Col); end if; Click2_Time := Event.Button.Time; end Touch_Tile; --\f procedure Tile_Remove (Event : X_Button_Press_Event) is ------------------------------------------------------------------------------ -- Called when the remove-selected-tile-pair mouse button is pressed. ------------------------------------------------------------------------------ begin if Click1 /= null and then Click2 /= null then Click2_Time := Event.Button.Time; Touch_Tile (Click2, Click2_Row, Click2_Col, Event); end if; end Tile_Remove; --\f function Touch (Bp : Board_Position; Event : X_Button_Press_Event) return Boolean is ------------------------------------------------------------------------------ -- Return TRUE if this XButtonEvent touched this Board_Position. ------------------------------------------------------------------------------ Face_X : S_Short := Bp.X + Bp.Level * Side_X; Face_Y : S_Short := Bp.Y - Bp.Level * Side_Y; begin ----Does this tile exist? if Bp.Level = 0 then return False; end if; ----Did we touch the face? if Event.Button.X >= Face_X and then Event.Button.X <= Face_X + Tile_Width + 1 and then Event.Button.Y >= Face_Y and then Event.Button.Y <= Face_Y + Tile_Height + 1 then return True; end if; ----Did we touch the side? if Event.Button.X >= Bp.X and then Event.Button.X <= Bp.X + Tile_Width + 1 and then Event.Button.Y >= Bp.Y and then Event.Button.Y <= Bp.Y + Tile_Height + 1 then return True; end if; ----Guess not. return False; end Touch; --\f procedure Tile_Press (Event : X_Button_Press_Event) is ------------------------------------------------------------------------------ -- Called when the Board receives a BtnDown event. ------------------------------------------------------------------------------ X : S_Short; Y : S_Short; Row : S_Short; Col : S_Short; begin ----Figure out a rough row/col coordinate for the click. Y := Event.Button.Y - Board_Tile0_Y; if Y < 0 then return; end if; Row := Y / (Tile_Height + 1); if Row > 7 then return; end if; X := Event.Button.X - Board_Tile0_X; if X < 0 then return; end if; Col := X / (Tile_Width + 1); if Col < 0 or else Row > 14 then goto Touched; end if; ----See if we are a special tile. if Col = 0 then if Touch (Board_Tiles (Spec3_Row, Spec3_Col), Event) then Touch_Tile (Board_Tiles (Spec3_Row, Spec3_Col), Spec3_Row, Spec3_Col, Event); goto Touched; end if; goto Touched; elsif Col = 13 then if Touch (Board_Tiles (Spec2_Row, Spec2_Col), Event) then Touch_Tile (Board_Tiles (Spec2_Row, Spec2_Col), Spec2_Row, Spec2_Col, Event); goto Touched; end if; if Touch (Board_Tiles (4, 12), Event) then Touch_Tile (Board_Tiles (4, 12), 4, 12, Event); goto Touched; end if; if Touch (Board_Tiles (3, 12), Event) then Touch_Tile (Board_Tiles (3, 12), 3, 12, Event); goto Touched; end if; goto Touched; elsif Col = Spec1_Col then if Touch (Board_Tiles (Spec1_Row, Spec1_Col), Event) then Touch_Tile (Board_Tiles (Spec1_Row, Spec1_Col), Spec1_Row, Spec1_Col, Event); goto Touched; end if; if Touch (Board_Tiles (Spec2_Row, Spec2_Col), Event) then Touch_Tile (Board_Tiles (Spec2_Row, Spec2_Col), Spec2_Row, Spec2_Col, Event); goto Touched; end if; goto Touched; elsif (Row = 3 or else Row = 4) and then (Col = 6 or else Col = 7) then if Touch (Board_Tiles (Spec4_Row, Spec4_Col), Event) then Touch_Tile (Board_Tiles (Spec4_Row, Spec4_Col), Spec4_Row, Spec4_Col, Event); goto Touched; end if; end if; ----See if the x/y falls exactly into somebody else's tile face. if Col > 0 and then Row < 7 then if Touch (Board_Tiles (Row + 1, Col - 1), Event) then Touch_Tile (Board_Tiles (Row + 1, Col - 1), Row + 1, Col - 1, Event); goto Touched; end if; end if; if Row < 7 then if Touch (Board_Tiles (Row + 1, Col), Event) then Touch_Tile (Board_Tiles (Row + 1, Col), Row + 1, Col, Event); goto Touched; end if; end if; if Col > 0 then if Touch (Board_Tiles (Row, Col - 1), Event) then Touch_Tile (Board_Tiles (Row, Col - 1), Row, Col - 1, Event); goto Touched; end if; end if; ----We don't have a touch on a neighbor so it must be us. if Touch (Board_Tiles (Row, Col), Event) then Touch_Tile (Board_Tiles (Row, Col), Row, Col, Event); goto Touched; end if; <<Touched>> null; end Tile_Press; --\f function Tile_Not_Free (Row : S_Short; Col : S_Short) return Boolean is ------------------------------------------------------------------------------ -- Returns TRUE if the tile has neither a left nor a right side free. ------------------------------------------------------------------------------ begin -- -- --The 4 in the center can be covered by SPEC4. if Row = 3 or else Row = 4 then if (Col = 6 or else Col = 7) and then Board_Tiles (Spec4_Row, Spec4_Col).Level > 0 then return True; elsif Col = 1 and then Board_Tiles (Spec3_Row, Spec3_Col).Level > 0 and then Board_Tiles (Row, Col + 1).Level > 0 then return True; elsif Col = 12 and then Board_Tiles (Spec2_Row, Spec2_Col).Level > 0 and then Board_Tiles (Row, Col - 1).Level > 0 then return True; end if; end if; ----If a tile has a neighbor then he isn't free. if Board_Tiles (Row, Col - 1).Level >= Board_Tiles (Row, Col).Level and then Board_Tiles (Row, Col + 1).Level >= Board_Tiles (Row, Col).Level then return True; end if; ----Check the special tiles. if Col = Spec1_Col then ----Tiles 1, 3, and 4 are always free. if Row /= Spec2_Row then return False; end if; ----Tile 2 is free if tile 1 is gone or if its two normal neighbors are gone. if Board_Tiles (Spec1_Row, Spec1_Col).Level > 0 and then (Board_Tiles (3, 12).Level > 0 or else Board_Tiles (4, 12).Level > 0) then return True; end if; end if; return False; end Tile_Not_Free; --\f procedure Tile_Release (Event : X_Button_Release_Event) is ------------------------------------------------------------------------------ -- Called when the Board receives a BtnUp event. ------------------------------------------------------------------------------ Tile1 : U_Char; Tile2 : U_Char; begin ----If there is a Click2 and if the tile type does not match with Click1 then ----nhilite Click2. if not Cheating and then Click1 /= null and then Click2 /= null then Tile1 := Click1.Tiles (S_Long (Click1.Level - 1)); Tile2 := Click2.Tiles (S_Long (Click2.Level - 1)); if -- Do tile faces match for those types that must match exactly? ((Tile1 > 8 or else Tile2 > 8) and then Tile1 /= Tile2) or else -- Are both tiles seasons? (Tile1 <= 4 and then Tile2 > 4) or else -- Are both tiles flowers? (Tile1 >= 5 and then Tile1 <= 8 and then (Tile2 < 5 or else Tile2 > 8)) then -- They don't match. if Dragon_Resources.Sticky_Tile then -- Simply remove tile 2 from selected tiles. Hilite_Tile (Click2_Row, Click2_Col); else -- Remove tile 1 from selection and make tile 2 => tile 1. Hilite_Tile (Click1_Row, Click1_Col); Click1 := Click2; Click1_Row := Click2_Row; Click1_Col := Click2_Col; Click2_Col := 0; -- Prevent dbl-clk removing 1 tile. end if; Click2 := null; Click2_Time := 0; end if; end if; ----If this tile has a left or a right neighbor then he isn't allowed. if not Cheating then if Click2 /= null and then Tile_Not_Free (Click2_Row, Click2_Col) then Hilite_Tile (Click2_Row, Click2_Col); Click2 := null; Click2_Time := 0; end if; if Click1 /= null and then Tile_Not_Free (Click1_Row, Click1_Col) then Hilite_Tile (Click1_Row, Click1_Col); Click1 := null; end if; end if; end Tile_Release; --\f procedure Next_Tile (Click : U_Char; Row : in out S_Short; Col : in out S_Short) is ------------------------------------------------------------------------------ -- Returns the "next" tile past row/col that exists and is "free". Returns 0,0 -- when we run out of tiles. ------------------------------------------------------------------------------ Tile1 : U_Char; Tile2 : U_Char; begin ----Loop until we give up. Advance the column. Advance the row on column -- verflow. Give up on row overflow. <<Continue>> null; Col := Col + 1; if Col > 14 then Col := 1; Row := Row + 1; if Row > 7 then Row := 0; Col := 0; return; end if; end if; ----Check this tile. If it doesn't exist or isn't free then ignore it. if Board_Tiles (Row, Col).Level = 0 then goto Continue; end if; if Tile_Not_Free (Row, Col) then goto Continue; end if; ----If moving Click1 then return now. if Click = 1 then return; end if; ----Continue the search if this tile does not match Click1. Tile1 := Click1.Tiles (S_Long (Click1.Level - 1)); Tile2 := Board_Tiles (Row, Col).Tiles (S_Long (Board_Tiles (Row, Col).Level - 1)); if -- Do tile faces match for those types that must match exactly? ((Tile1 > 8 or else Tile2 > 8) and then Tile1 /= Tile2) or else -- Are both tiles seasons? (Tile1 <= 4 and then Tile2 > 4) or else -- Are both tiles flowers? (Tile1 >= 5 and then Tile1 <= 8 and then (Tile2 < 5 or else Tile2 > 8)) then -- They don't match. goto Continue; end if; end Next_Tile; --\f procedure Hints (Event : X_Button_Press_Event) is ------------------------------------------------------------------------------ -- If Click1 not present then search for the "first" remaining tile otherwise -- use Click1 as our current "base" tile. -- If Click1 present but not Click2 then search for any match for Click1. -- If Click2 not present either then search for the first remaining tile past -- Click1 otherwise search for the first remaining tile past Click2. -- Keep searching for a new Click2 until we hit a matching tile or until we -- run out. Exit on match with new tile as Click2. -- Advance Click1 and start a new search for Click2. If we run out on Click1 -- then remove Click1. ------------------------------------------------------------------------------ begin ----If we have a Click1 but no Click2 then search for a Click2. if Click1 /= null and then Click2 = null then One_Button_Hint := True; Click2_Row := 0; Click2_Col := 0; loop Next_Tile (2, Click2_Row, Click2_Col); if Click2_Col = 0 then One_Button_Hint := False; Hilite_Tile (Click1_Row, Click1_Col); Click1 := null; return; end if; if Click2_Row /= Click1_Row or else Click2_Col /= Click1_Col then Click2 := Board_Tiles (Click2_Row, Click2_Col); Hilite_Tile (Click2_Row, Click2_Col); return; end if; end loop; end if; ----Find a Click1 to work with if we don't already have one. if Click1 = null then Click1_Row := 0; Click1_Col := 0; Next_Tile (1, Click1_Row, Click1_Col); if Click1_Col = 0 then return; end if; Hilite_Tile (Click1_Row, Click1_Col); Click1 := Board_Tiles (Click1_Row, Click1_Col); end if; ----Find our starting position for Click2 if we don't have one. if Click2 = null then Click2_Row := Click1_Row; Click2_Col := Click1_Col; else Hilite_Tile (Click2_Row, Click2_Col); Click2 := null; end if; ----Loop until we get something. loop Next_Tile (2, Click2_Row, Click2_Col); if Click2_Col /= 0 then if Click2_Row /= Click1_Row or else Click2_Col /= Click1_Col then Click2 := Board_Tiles (Click2_Row, Click2_Col); Hilite_Tile (Click2_Row, Click2_Col); return; end if; else Hilite_Tile (Click1_Row, Click1_Col); Click1 := null; if One_Button_Hint then One_Button_Hint := False; return; end if; Next_Tile (1, Click1_Row, Click1_Col); if Click1_Col = 0 then return; end if; Hilite_Tile (Click1_Row, Click1_Col); Click1 := Board_Tiles (Click1_Row, Click1_Col); Click2_Row := Click1_Row; Click2_Col := Click1_Col; end if; end loop; end Hints; --\f begin declare Clk : Calendar.Day_Duration := Calendar.Seconds (Calendar.Clock); I : Natural; begin I := Natural (Clk / Duration (100.0)); Clk := Calendar.Day_Duration (Clk - Duration (Duration (I) * Duration (100.00))); ----Clk is now in the 0..99.9999 range. Ran_Data := Ran1_Initialize (S_Natural (Float (Clk) * Float (Natural'Last / 101))); end; end Board;