| (* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 |
| Free Software Foundation, Inc. *) |
| (* This file is part of GNU Modula-2. |
| |
| GNU Modula-2 is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 3, or (at your option) any later |
| version. |
| |
| GNU Modula-2 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. See the GNU General Public License |
| for more details. |
| |
| You should have received a copy of the GNU General Public License along |
| with gm2; see the file COPYING. If not, write to the Free Software |
| Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) |
| IMPLEMENTATION MODULE MakeBoxes ; |
| |
| |
| FROM StrIO IMPORT WriteString, WriteLn ; |
| |
| FROM Chance IMPORT GetRand ; |
| |
| |
| CONST |
| MaxBox = 15000 ; |
| MaxIndex = 500 ; |
| |
| TYPE |
| Box = RECORD |
| LengthX, |
| LengthY: CARDINAL ; |
| END ; |
| |
| Index = RECORD |
| Start, (* Start of the Box list *) |
| End : CARDINAL ; (* End of the Box list *) |
| END ; |
| |
| VAR |
| BoxIndex : ARRAY [0..MaxIndex] OF Index ; |
| Boxes : ARRAY [1..MaxBox] OF Box ; |
| NoOfBoxes : CARDINAL ; (* Number of boxes in array Boxes *) |
| NoOfIndices: CARDINAL ; (* Number of indices in BoxIndex *) |
| |
| |
| (* |
| InitBoxes - Initializes a list of boxes. |
| An index to this box list is returned. |
| *) |
| |
| PROCEDURE InitBoxes () : CARDINAL ; |
| BEGIN |
| IF NoOfIndices=MaxIndex |
| THEN |
| WriteString('Too many box list indices in Module MakeBoxes') ; |
| WriteLn ; |
| WriteString('Increase MaxIndex') ; |
| WriteLn ; |
| HALT |
| ELSE |
| INC(NoOfIndices) ; |
| WITH BoxIndex[NoOfIndices] DO |
| Start := NoOfBoxes+1 ; |
| End := NoOfBoxes |
| END ; |
| RETURN(NoOfIndices) |
| END |
| END InitBoxes ; |
| |
| |
| (* |
| AddBoxes - Adds a list of boxes MinX..MaxX, MinY..MaxY |
| to a box list BoxListIndex. |
| *) |
| |
| PROCEDURE AddBoxes (BoxListIndex: CARDINAL; |
| MinX, MinY, MaxX, MaxY: CARDINAL) ; |
| BEGIN |
| WITH BoxIndex[BoxListIndex] DO |
| Expand(BoxListIndex, MinX, MinY, MaxX, MaxY) ; |
| End := NoOfBoxes |
| END |
| END AddBoxes ; |
| |
| |
| (* |
| Expand - expands the box limitations MinX..MaxX, MinY..MaxY for all |
| possibilities of boxes. |
| *) |
| |
| PROCEDURE Expand (BoxListIndex: CARDINAL; |
| MinX, MinY, MaxX, MaxY: CARDINAL) ; |
| VAR |
| i, j: CARDINAL ; |
| BEGIN |
| i := MinX ; |
| WHILE i<=MaxX DO |
| j := MinY ; |
| WHILE j<=MaxY DO |
| AddBox(BoxListIndex, i, j) ; |
| INC(j) |
| END ; |
| INC(i) |
| END |
| END Expand ; |
| |
| |
| (* |
| AddBox - adds a box of Width, Height to a list of boxes specified by |
| BoxListIndex. |
| *) |
| |
| PROCEDURE AddBox (BoxListIndex: CARDINAL; |
| Width, Height: CARDINAL) ; |
| BEGIN |
| IF NoOfBoxes=MaxBox |
| THEN |
| WriteString('Too many boxes in a list in Module MakeBoxes') ; |
| WriteLn ; |
| WriteString('Increase MaxBox') ; |
| WriteLn ; |
| HALT |
| ELSIF UniqueBox(BoxListIndex, Width, Height) |
| THEN |
| INC(NoOfBoxes) ; |
| WITH Boxes[NoOfBoxes] DO |
| LengthX := Width ; |
| LengthY := Height |
| END |
| END |
| END AddBox ; |
| |
| |
| (* |
| UniqueBox - returns true if a box Width, Height is unique in the |
| box list BoxListIndex. |
| *) |
| |
| PROCEDURE UniqueBox (BoxListIndex: CARDINAL; |
| Width, Height: CARDINAL) : BOOLEAN ; |
| VAR |
| i : CARDINAL ; |
| Found: BOOLEAN ; |
| BEGIN |
| WITH BoxIndex[BoxListIndex] DO |
| i := Start ; |
| Found := FALSE ; |
| WHILE (NOT Found) AND (i<=End) DO |
| WITH Boxes[i] DO |
| Found := (LengthX=Width) AND (LengthY=Height) |
| END ; |
| INC(i) |
| END |
| END ; |
| RETURN( NOT Found ) |
| END UniqueBox ; |
| |
| |
| (* |
| KillBoxes - Kills a complete box list. |
| *) |
| |
| PROCEDURE KillBoxes (BoxListIndex: CARDINAL) ; |
| BEGIN |
| IF NoOfIndices>0 |
| THEN |
| (* Destroy index to box list *) |
| WITH BoxIndex[BoxListIndex] DO |
| Start := 0 ; |
| End := 0 |
| END ; |
| (* |
| If killed last box list see if we can garbage collect |
| previously killed middle indices. |
| *) |
| IF NoOfIndices=BoxListIndex |
| THEN |
| REPEAT |
| DEC(NoOfIndices) |
| UNTIL (NoOfIndices=0) OR (BoxIndex[NoOfIndices].Start#0) |
| END ; |
| NoOfBoxes := BoxIndex[NoOfIndices].End |
| ELSE |
| WriteString('All boxes have been killed - Module MakeBoxes') ; |
| WriteLn ; |
| HALT |
| END |
| END KillBoxes ; |
| |
| |
| (* |
| GetAndDeleteRandomBox - Returns a random box from the box list and |
| this box is then deleted from the list. |
| *) |
| |
| PROCEDURE GetAndDeleteRandomBox (BoxListIndex: CARDINAL; |
| VAR SizeX, SizeY: CARDINAL) ; |
| VAR |
| i, j: CARDINAL ; |
| BEGIN |
| WITH BoxIndex[BoxListIndex] DO |
| i := Start+GetRand(End-Start+1) ; (* +1 for GetRand *) |
| j := i ; |
| REPEAT |
| IF Boxes[j].LengthX=0 |
| THEN |
| INC(j) ; |
| IF j>End |
| THEN |
| j := Start |
| END |
| END |
| UNTIL (j=i) OR (Boxes[j].LengthX#0) ; |
| WITH Boxes[j] DO |
| SizeX := LengthX ; |
| SizeY := LengthY ; |
| LengthX := 0 ; (* Now delete this box *) |
| LengthY := 0 |
| END |
| END |
| END GetAndDeleteRandomBox ; |
| |
| |
| PROCEDURE Init ; |
| BEGIN |
| NoOfBoxes := 0 ; |
| NoOfIndices := 0 ; |
| WITH BoxIndex[NoOfIndices] DO |
| End := 0 |
| END |
| END Init ; |
| |
| |
| BEGIN |
| Init |
| END MakeBoxes. |