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: 31382 (0x7a96) 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 Puz_Main; use Puz_Main; with Ran1_Package; use Ran1_Package; package body Puz_Puzzle is ------------------------------------------------------------------------------ -- $Header: puzzle.c,v 1.3 88/02/24 15:42:56 rws Exp $ ------------------------------------------------------------------------------ -- Puzzle - (C) Copyright 1987, 1988 Don Bennett. -- -- Permission to use, copy, modify, and distribute this software and its -- documentation for any purpose and without fee is hereby granted, -- provided that the above copyright notice appear in all copies and that -- both that copyright notice and this permission notice appear in -- supporting documentation. ------------------------------------------------------------------------------ -- static char *rcsid_puzzle_c = "$Header: puzzle.c,v 1.3 88/02/24 15:42:56 rws Exp $"; ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Puzzle -- -- Don Bennett, HP Labs -- -- this is the code that does the real work to solve the -- puzzle. (Commonly seen as a 4x4 grid of sliding pieces -- numbered 1-15 with one empty space.) -- -- The idea for the solution algorithm - solving the puzzle -- in layers working from the outside in - comes to me -- indirectly from John Nagle. ------------------------------------------------------------------------------ type Direction_S_Long is array (Direction) of S_Long; Ran_Data : Ran1_Data; Max_Plan : constant := 1000; Other_Dir : constant Direction_Array (0 .. 3) := (Right, Left, Down, Up); Solving_Flag : Boolean := False; Abort_Solving_Flag : Boolean := False; Extra_Rows : S_Natural := 0; Extra_Columns : S_Natural := 0; Layers : S_Natural; Tmp_Matrix : S_Long_2d_Access; Target : S_Long_2d_Access; Locked : S_Long_2d_Access; Link : Direction_List; Solve_Env : exception; --\f -- layer info macros -> (innermost 4 tiles are layer zero, ordinal goes up -- as you move out) -- layer_depth - returns number of (rows down),(cols across) the layer starts; -- layer_width - number of blocks wide the layer is; function Layer_Depth (L : S_Natural) return S_Natural is begin return Layers - 1 - L; end Layer_Depth; function Layer_Width (L : S_Natural) return S_Natural is begin return Puzzle_Size - 2 * Layer_Depth (L); end Layer_Width; -- /** macros for finding the corners of each layer **/ function Ful (L : S_Natural) return S_Natural is begin return Layer_Depth (L) * (Puzzle_Size + 1) + Extra_Rows * Puzzle_Width + Extra_Columns * (Layers - (L)); end Ful; function Fur (L : S_Natural) return S_Natural is begin return Layer_Depth (L) * (Puzzle_Size + 1) + Layer_Width (L) - 1 + Extra_Rows * Puzzle_Width + Extra_Columns * (Layers - (L)); end Fur; function Fll (L : S_Natural) return S_Natural is begin return (Layer_Depth (L) + Layer_Width (L) - 1) * Puzzle_Size + Layer_Depth (L) + Extra_Rows * Puzzle_Size + Extra_Columns * (Puzzle_Height + 1 + (L) - Layers); end Fll; function Flr (L : S_Natural) return S_Natural is begin return (Layer_Depth (L) + Layer_Width (L) - 1) * (Puzzle_Size + 1) + Extra_Rows * Puzzle_Size + Extra_Columns * (Puzzle_Height + 1 + (L) - Layers); end Flr; -- /** get the x and y coordinates of a location in the matrix **/ function Get_X (Loc : S_Long) return S_Long is begin return S_Long (Loc) rem S_Long (Puzzle_Width); end Get_X; function Get_Y (Loc : S_Long) return S_Long is begin return S_Long (Loc) / S_Long (Puzzle_Width); end Get_Y; function Indx (X, Y : S_Long) return S_Long is begin return Y * S_Long (Puzzle_Width) + X; end Indx; function Next_Left (Loc : S_Long) return S_Long is begin return Loc - 1; end Next_Left; function Next_Right (Loc : S_Long) return S_Long is begin return Loc + 1; end Next_Right; function Next_Up (Loc : S_Long) return S_Long is begin return Loc - S_Long (Puzzle_Width); end Next_Up; function Next_Down (Loc : S_Long) return S_Long is begin return Loc + Puzzle_Width; end Next_Down; --\f ------------------------------------------------------------------------------ -- this piece of code needs to be fixed if you want to use it -- for non-square matrices; ------------------------------------------------------------------------------ procedure Print_Matrix (Mat : S_Long_2d) is begin Text_Io.New_Line; for I in 0 .. Puzzle_Height - 1 loop for J in 0 .. Puzzle_Width - 1 loop Text_Io.Put (' '); S_Long_Io.Put (Mat (Indx (J, I)), 2); Text_Io.Put (' '); end loop; Text_Io.New_Line; end loop; Text_Io.New_Line; end Print_Matrix; --\f procedure Plan_Move (Start_Loc : S_Natural; End_Loc : S_Natural; Path : in out Direction_Array; Path_End : in out S_Natural); function Find_Piece (Piece : S_Natural) return S_Natural is begin for I in 0 .. S_Natural (Puzzle_Width * Puzzle_Height - 1) loop if Position (I) = Piece then return I; end if; end loop; -- text_io.put_line("piece %d not found!\n",piece); raise Program_Error; end Find_Piece; --\f procedure Move_Space (Diri : Direction; Disti : S_Long); procedure Move_Space_To (Loc : S_Natural) is Current_Dir : Direction; Dist : S_Natural; Plan : Direction_Array (0 .. Max_Plan - 1); Plan_End : S_Natural := 0; begin Plan_Move (Indx (Space_X, Space_Y), Loc, Plan, Plan_End); Current_Dir := Plan (1); Dist := 0; for I in 1 .. Plan_End loop if Plan (I) = Current_Dir then Dist := Dist + 1; elsif Plan (I) = Other_Dir (Direction'Pos (Current_Dir)) then Dist := Dist - 1; else Move_Space (Current_Dir, Dist); Current_Dir := Plan (I); Dist := 1; end if; end loop; Move_Space (Current_Dir, Dist); end Move_Space_To; --\f procedure Move_Piece (Loci : S_Natural; Target : S_Natural) is Loc : S_Natural := Loci; Plan : Direction_Array (0 .. Max_Plan - 1); Plan_End : S_Natural := 0; begin Plan_Move (Loc, Target, Plan, Plan_End); for I in 1 .. Plan_End loop case Plan (I) is when Left => Locked (Loc) := 1; Move_Space_To (Next_Left (Loc)); Locked (Loc) := 0; Move_Space_To (Loc); Loc := Next_Left (Loc); when Right => Locked (Loc) := 1; Move_Space_To (Next_Right (Loc)); Locked (Loc) := 0; Move_Space_To (Loc); Loc := Next_Right (Loc); when Up => Locked (Loc) := 1; Move_Space_To (Next_Up (Loc)); Locked (Loc) := 0; Move_Space_To (Loc); Loc := Next_Up (Loc); when Down => Locked (Loc) := 1; Move_Space_To (Next_Down (Loc)); Locked (Loc) := 0; Move_Space_To (Loc); Loc := Next_Down (Loc); when None => raise Program_Error; end case; end loop; end Move_Piece; --\f procedure Plan_Move (Start_Loc : S_Natural; End_Loc : S_Natural; Path : in out Direction_Array; Path_End : in out S_Natural) is Queue_Size : constant := 1000; Next_Loc : S_Natural; Next_Dist : S_Natural; Chosen : S_Natural; Found_Path : S_Natural; Move_Num : S_Natural; Loc_X : S_Long; Loc_Y : S_Long; Loc_Queue : S_Long_2d (0 .. Queue_Size - 1); Loc_Dist : S_Long_2d (0 .. Queue_Size - 1); Loc_Queue_Used : S_Long_2d (0 .. Queue_Size - 1); Queue_Head : S_Natural; Queue_Tail : S_Natural; Candidate : Direction_S_Long; function Dist (Loc1, Loc2 : S_Natural) return S_Natural is begin return S_Natural (abs (Get_X (Loc1) - Get_X (Loc2)) + abs (Get_Y (Loc1) - Get_Y (Loc2))); end Dist; begin Found_Path := 0; for I in 0 .. Puzzle_Width * Puzzle_Height - 1 loop Tmp_Matrix (I) := -Locked (I); Link (I) := None; end loop; Loc_Queue_Used := (others => 0); Queue_Head := 0; Queue_Tail := 0; Loc_Queue (0) := Start_Loc; Loc_Dist (0) := Dist (End_Loc, Start_Loc); Tmp_Matrix (Start_Loc) := 1; Queue_Tail := Queue_Tail + 1; -- if the selected element has a distance of zero, we've found it; -- (This really isn't a queue, but rather a range of elements -- to be searched for an element of the desired properties; -- as we search for a path, -- LINK array is used to indicate the direction from which -- we moved into a location; -- TMP_MATRIX array is used to keep track of the move number; while Queue_Head < Queue_Tail and then Found_Path = 0 loop -- find the entry that -- (1) has the smallest distance and -- (2) has the smallest move number; Next_Loc := Loc_Queue (Queue_Head); Next_Dist := Loc_Dist (Queue_Head); Chosen := Queue_Head; for I in Queue_Head + 1 .. Queue_Tail - 1 loop if Loc_Queue_Used (I) = 0 and then (Loc_Dist (I) < Next_Dist or else (Loc_Dist (I) = Next_Dist and then Tmp_Matrix (Loc_Queue (I)) < Tmp_Matrix (Next_Loc))) then Next_Loc := Loc_Queue (I); Next_Dist := Loc_Dist (I); Chosen := I; end if; end loop; if Next_Dist = 0 then Found_Path := 1; exit; end if; Loc_Queue_Used (Chosen) := 1; -- /********************************/ -- /** permute the chosen element **/ -- /********************************/ Candidate (Left) := Next_Left (Next_Loc); Candidate (Right) := Next_Right (Next_Loc); Candidate (Up) := Next_Up (Next_Loc); Candidate (Down) := Next_Down (Next_Loc); Loc_X := Get_X (Next_Loc); Loc_Y := Get_Y (Next_Loc); if Loc_X = 0 then Candidate (Left) := -1; end if; if Loc_X = Puzzle_Width - 1 then Candidate (Right) := -1; end if; if Loc_Y = 0 then Candidate (Up) := -1; end if; if Loc_Y = Puzzle_Height - 1 then Candidate (Down) := -1; end if; Move_Num := Tmp_Matrix (Next_Loc) + 1; for I in Left .. Down loop if Candidate (I) /= -1 and then Tmp_Matrix (Candidate (I)) = 0 then Tmp_Matrix (Candidate (I)) := Move_Num; -- the next line works because the candidate index is -- same as the direction moved to reach the candidate; Link (Candidate (I)) := I; Loc_Queue (Queue_Tail) := Candidate (I); Loc_Dist (Queue_Tail) := Dist (End_Loc, Candidate (I)); Queue_Tail := Queue_Tail + 1; if Queue_Tail = Queue_Size then goto Broke; end if; end if; end loop; -- /***************************************************/ -- /** delete used items from the front of the queue **/ -- /***************************************************/ while Loc_Queue_Used (Queue_Head) /= 0 and then Queue_Head < Queue_Tail loop Queue_Head := Queue_Head + 1; end loop; end loop; if Found_Path = 0 then Text_Io.Put_Line ("couldn't find a way to move (" & S_Long'Image (Get_X (Start_Loc)) & "," & S_Long'Image (Get_Y (Start_Loc)) & ") to (" & S_Long'Image (Get_X (End_Loc)) & "," & S_Long'Image (Get_Y (End_Loc)) & ")."); Print_Matrix (Position.all); Text_Io.New_Line; Print_Matrix (Locked.all); Text_Io.New_Line; Path_End := 0; return; end if; <<Broke>> null; if Queue_Tail = Queue_Size then Text_Io.Put_Line ("it didn't work."); Path_End := 0; return; end if; -- /** copy the path we found into the path array; -- ** element 0 will contain the number of moves in the path; -- **/ -- -- /** by the time we get there, next_loc is in the final location **/ Path_End := Tmp_Matrix (Next_Loc) - 1; for I in reverse 1 .. Path_End loop Path (I) := Link (Next_Loc); case Link (Next_Loc) is when Left => Next_Loc := Next_Right (Next_Loc); when Right => Next_Loc := Next_Left (Next_Loc); when Up => Next_Loc := Next_Down (Next_Loc); when Down => Next_Loc := Next_Up (Next_Loc); when None => raise Program_Error; end case; end loop; end Plan_Move; --\f procedure Move_Space (Diri : Direction; Disti : S_Long) is Dir : Direction := Diri; Dist : S_Long := Disti; Step : S_Long; Count : S_Long; Min_X : S_Long; Min_Y : S_Long; Max_X : S_Long; Max_Y : S_Long; First_X : S_Long; First_Y : S_Long; Last_X : S_Long; Last_Y : S_Long; Shift_Dir : Direction; begin ----Process events if we are Solving but not if we are already processing -- events as that may cause us to process them in incorrect order. if Solving_Flag and then not Abort_Solving_Flag and then Puzzle_Pending /= 0 then Process_Events; end if; if Solving_Flag and then Abort_Solving_Flag then raise Solve_Env; end if; if Dist = 0 then return; end if; if Dir = Left then Dir := Right; Dist := -Dist; end if; if Dir = Up then Dir := Down; Dist := -Dist; end if; First_X := Space_X; First_Y := Space_Y; Step := 1; Count := Dist; if Dist < 0 then Step := -1; Count := -Count; end if; -- /** first_x,y are the location of the first piece to be shifted **/ if Dir = Right then First_X := First_X + Step; else First_Y := First_Y + Step; end if; -- /** shift_dir is the direction the pieces need to be shifted **/ if Dist < 0 then Shift_Dir := Dir; else case Dir is when Left => Shift_Dir := Right; when Right => Shift_Dir := Left; when Up => Shift_Dir := Down; when Down => Shift_Dir := Up; when None => raise Program_Error; end case; end if; for I in 0 .. Count - 1 loop if Dir = Right then Position (Indx (Space_X, Space_Y)) := Position (Indx (Space_X + Step, Space_Y)); Position (Indx (Space_X + Step, Space_Y)) := 0; Space_X := Space_X + Step; -- /** dir = DOWN **/ else Position (Indx (Space_X, Space_Y)) := Position (Indx (Space_X, Space_Y + Step)); Position (Indx (Space_X, Space_Y + Step)) := 0; Space_Y := Space_Y + Step; end if; end loop; Last_X := Space_X; Last_Y := Space_Y; -- /** the blocks first_x,y through last_x,y need to be shifted -- ** one block in the shift_dir direction; -- **/ if Output_Logging then Log_Move_Space (First_X, First_Y, Last_X, Last_Y, Shift_Dir); end if; end Move_Space; --\f procedure Initialize is -- /** Initialize the position and -- ** the target matrices; -- **/ -- Sp_X : S_Long; Sp_Y : S_Long; begin Layers := Puzzle_Size / 2; Extra_Rows := Puzzle_Height - Puzzle_Size; Extra_Columns := Puzzle_Width - Puzzle_Size; Position := new S_Long_2d (0 .. Puzzle_Width * Puzzle_Height - 1); Tmp_Matrix := new S_Long_2d (0 .. Puzzle_Width * Puzzle_Height - 1); Target := new S_Long_2d (0 .. Puzzle_Width * Puzzle_Height - 1); Locked := new S_Long_2d (0 .. Puzzle_Width * Puzzle_Height - 1); Link := new Direction_Array (0 .. Puzzle_Width * Puzzle_Height - 1); Locked.all := (Locked.all'Range => 0); for I in 0 .. Puzzle_Width * Puzzle_Height - 1 loop Target (I) := I + 1; Position (I) := I + 1; end loop; Position (Position'Last) := 0; Target (Target'Last) := 0; Space_X := Puzzle_Width - 1; Space_Y := Puzzle_Height - 1; -- /** Move the space into the LR corner of the -- ** innermost layer; -- ** For each of the outer layers, move the space -- ** left one and up one; -- **/ Sp_X := Space_X; Sp_Y := Space_Y; for I in 0 .. Layers - 2 loop -- /** move the space left one; **/ Target (Indx (Sp_X, Sp_Y)) := Target (Indx (Sp_X - 1, Sp_Y)); Target (Indx (Sp_X - 1, Sp_Y)) := 0; Sp_X := Sp_X - 1; -- /** move the space up one; **/ Target (Indx (Sp_X, Sp_Y)) := Target (Indx (Sp_X, Sp_Y - 1)); Target (Indx (Sp_X, Sp_Y - 1)) := 0; Sp_Y := Sp_Y - 1; end loop; end Initialize; --\f function Random return S_Natural is begin return S_Natural (Ran1 (Ran_Data) * Float (S_Natural'Last - 1)); end Random; --\f procedure Scramble is New_X : S_Long; New_Y : S_Long; Old_Output_State : Boolean; begin Old_Output_State := Output_Logging; Output_Logging := False; for I in 0 .. 10 * Puzzle_Width * Puzzle_Height - 1 loop New_X := S_Long (Ran1 (Ran_Data) * Float (Puzzle_Width - 1)); New_Y := S_Long (Ran1 (Ran_Data) * Float (Puzzle_Height - 1)); Move_Space (Right, New_X - Space_X); Move_Space (Down, New_Y - Space_Y); end loop; Output_Logging := Old_Output_State; end Scramble; --\f -- /** To solve this puzzle, work from the outside in; -- ** For each successive ring working your way in, -- ** -- ** (1) put the corners in place; -- ** (2) finish off the rest of the boundaries; -- ** (3) do the next layer in; -- **/ procedure Solve_Layer_0 is begin Move_Piece (Find_Piece (Target (Ful (0))), Ful (0)); Move_Space_To (Flr (0)); end Solve_Layer_0; procedure Do_Last_Two_On_Edge (Ntlast : S_Natural; Last : S_Natural; Tmp : S_Natural; Emergency : S_Natural) is Last_Piece : S_Natural; Ntlast_Piece : S_Natural; begin Last_Piece := Target (Last); Ntlast_Piece := Target (Ntlast); Move_Piece (Find_Piece (Ntlast_Piece), Last); Locked (Last) := 1; -- /** if the last piece is stuck where the next to the last -- ** piece should go, do some magic to fix things up; -- **/ if Find_Piece (0) = Ntlast then Move_Space_To (Tmp); end if; if Find_Piece (Last_Piece) = Ntlast then -- /** a rescue is necessary **/ Locked (Last) := 0; Move_Piece (Find_Piece (Ntlast_Piece), Ntlast); Locked (Ntlast) := 1; Move_Piece (Find_Piece (Last_Piece), Emergency); Locked (Emergency) := 1; Locked (Ntlast) := 0; Move_Piece (Find_Piece (Ntlast_Piece), Last); Locked (Emergency) := 0; Locked (Last) := 1; end if; Move_Piece (Find_Piece (Last_Piece), Tmp); Locked (Tmp) := 1; Move_Space_To (Ntlast); Locked (Tmp) := 0; Locked (Last) := 0; Move_Space_To (Last); Move_Space_To (Tmp); Locked (Ntlast) := 1; Locked (Last) := 1; end Do_Last_Two_On_Edge; --\f procedure Solve_Layer (Layer : S_Natural) is Tmp : S_Long; Last : S_Long; Ntlast : S_Long; Emergency : S_Long; Ul : S_Long; Ur : S_Long; Ll : S_Long; Lr : S_Long; begin if Layer = 0 then Solve_Layer_0; else -- /** find and put each of the corners into place **/ Ul := Ful (Layer); Ur := Fur (Layer); Ll := Fll (Layer); Lr := Flr (Layer); Move_Piece (Find_Piece (Target (Ul)), Ul); Locked (Ul) := 1; Move_Piece (Find_Piece (Target (Ur)), Ur); Locked (Ur) := 1; Move_Piece (Find_Piece (Target (Ll)), Ll); Locked (Ll) := 1; Move_Piece (Find_Piece (Target (Lr)), Lr); Locked (Lr) := 1; -- /** Strategy for doing the pieces between the corners: -- ** (1) put all but the last two edge pieces in place; -- ** (2) put the next to the last piece next to the corner; -- ** (3) put the last piece one move in from its final position; -- ** (4) move the space to the final position of the next -- ** to the last piece; -- ** (5) slide the next to the last piece over and the last -- ** piece into the edge where it goes. -- **/ -- -- /**************/ -- /** top edge **/ -- /**************/ for I in Ul + 1 .. Ur - 3 loop Move_Piece (Find_Piece (Target (I)), I); Locked (I) := 1; end loop; Ntlast := Ur - 2; Last := Ur - 2 + 1; Tmp := Fur (Layer - 1); Emergency := Next_Down (Tmp); Do_Last_Two_On_Edge (Ntlast, Last, Tmp, Emergency); -- /*****************/ -- /** bottom edge **/ -- /*****************/ for I in Ll + 1 .. Lr - 3 loop Move_Piece (Find_Piece (Target (I)), I); Locked (I) := 1; end loop; Ntlast := Lr - 2; Last := Lr - 2 + 1; Tmp := Flr (Layer - 1); Emergency := Next_Up (Tmp); Do_Last_Two_On_Edge (Ntlast, Last, Tmp, Emergency); -- /***************/ -- /** left side **/ -- /***************/ declare I : S_Natural; begin I := Ul + Puzzle_Width; while I < Ll - 2 * Puzzle_Width loop Move_Piece (Find_Piece (Target (I)), I); Locked (I) := 1; I := I + Puzzle_Width; end loop; end; Ntlast := Ll - 2 * Puzzle_Width; Last := Ll - 2 * Puzzle_Width + Puzzle_Width; Tmp := Fll (Layer - 1); Emergency := Next_Right (Tmp); Do_Last_Two_On_Edge (Ntlast, Last, Tmp, Emergency); -- /****************/ -- /** right side **/ -- /****************/ declare I : S_Natural := Ur + Puzzle_Width; begin while I < Lr - 2 * Puzzle_Width loop Move_Piece (Find_Piece (Target (I)), I); Locked (I) := 1; I := I + Puzzle_Width; end loop; Ntlast := I; Last := I + Puzzle_Width; Tmp := Flr (Layer - 1); Emergency := Next_Left (Tmp); Do_Last_Two_On_Edge (Ntlast, Last, Tmp, Emergency); end; end if; -- if Master_Debug then -- Text_Io.Put_Line ("Just did layer " & s_natural'Image (Layer)); -- Print_Matrix (Position.all); -- end if; end Solve_Layer; --\f procedure Solve_Row (Row : S_Natural) is Loc : S_Long; Last : S_Long; Ntlast : S_Long; Tmp : S_Long; Emergency : S_Long; begin for I in 0 .. Puzzle_Width - 3 loop Loc := Indx (I, Row); Move_Piece (Find_Piece (Target (Loc)), Loc); Locked (Loc) := 1; end loop; Ntlast := Indx (Puzzle_Width - 2, Row); Last := Indx (Puzzle_Width - 1, Row); Tmp := Last + Puzzle_Width; Emergency := Tmp + Puzzle_Width; Do_Last_Two_On_Edge (Ntlast, Last, Tmp, Emergency); end Solve_Row; --\f procedure Solve_Col (Col : S_Natural) is Loc : S_Long; Last : S_Long; Ntlast : S_Long; Tmp : S_Long; Emergency : S_Long; begin for I in 0 .. Puzzle_Height - 3 loop Loc := Indx (Col, I); Move_Piece (Find_Piece (Target (Loc)), Loc); Locked (Loc) := 1; end loop; Ntlast := Indx (Col, Puzzle_Height - 2); Last := Indx (Col, Puzzle_Height - 1); Tmp := Last + 1; Emergency := Tmp + 1; Do_Last_Two_On_Edge (Ntlast, Last, Tmp, Emergency); end Solve_Col; --\f procedure Abort_Solving is begin if Solving_Flag then Abort_Solving_Flag := True; end if; end Abort_Solving; --\f function Solving_Status return Boolean is begin return Solving_Flag; end Solving_Status; --\f procedure Solve is begin -- /** determine the position we want to be in when -- ** we are done; This position will have the space in -- ** the center; Then, we'll move the space back to -- ** the outside. -- **/ -- if Solving_Flag then return; end if; begin Solving_Flag := True; Locked.all := (Locked.all'Range => 0); -- /** solve the extra rows and cols **/ for I in 0 .. Extra_Rows - 1 loop Solve_Row (I); end loop; for I in 0 .. Extra_Columns - 1 loop Solve_Col (I); end loop; -- /** solve each layer **/ for I in reverse 0 .. Layers - 1 loop Solve_Layer (I); end loop; -- /** move the space back out to the LR corner; **/ -- /** i is the layer the space is moving into **/ for I in 1 .. Layers - 1 loop Move_Space (Down, 1); Move_Space (Right, 1); end loop; Flush_Logging; exception when Solve_Env => Flush_Logging; Repaint_Tiles; end; Locked.all := (Locked.all'Range => 0); Abort_Solving_Flag := False; Solving_Flag := False; end Solve; --\f -- procedure Main is -- Plan : Direction_Array (0 .. 1000 - 1); -- begin -- -- Master_Debug := True; -- Initialize; -- -- Print_Matrix (Position.all); -- -- Scramble; -- -- Print_Matrix (Position.all); -- -- -- #ifdef UDEFINED -- -- locked(indx(4,3)) := 1; -- -- locked(indx(4,2)) := 1; -- -- locked(indx(4,1)) := 1; -- -- locked(indx(5,2)) := 1; -- -- -- -- plan_move(indx(space_x,space_y),indx(5,1),plan); -- -- print_matrix(tmp_matrix); -- -- printf("\nplan has %d moves.\n",plan(0)); -- -- for (i:=0; i<plan(0); i++) { -- -- switch(plan(i+1)) { -- -- case UP: printf("up\n"); -- -- break; -- -- case DOWN: printf("down\n"); -- -- break; -- -- case LEFT: printf("left\n"); -- -- break; -- -- case RIGHT: printf("right\n"); -- -- break; -- -- } -- -- } -- -- #endif /* UDEFINED */ -- -- Solve; -- -- Print_Matrix (Position.all); -- Master_Debug := False; -- -- end Main; 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 Puz_Puzzle;