
with splaylist;
with text_io;

with Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Text_IO;

with ada.command_line;
with ada.calendar;


package utils is


use Ada.Strings.Unbounded;
use Ada.Strings.Unbounded.Text_IO;


	package myint_io is new text_io.integer_io(integer);

	package myfloat_io is new text_io.float_io(float);

	procedure myassert( 
		condition : boolean;  
		flag: integer:=0;
		msg: string := "");




	failure: boolean := false;
	tsec0, tsec1 : ada.calendar.day_duration;






--------------- begin types for hashtable --------------------------

	--type ubyte is range 0..255; --(1-byte)
	--type ushort is range 0..2**32-1; -- (4-bytes)
	-- note that 8-byte integers may not be defined in above fashion.

	-- Be careful with these modular types because subtraction
	-- and division do not function normally.  The usage here 
	-- only requires addition & multiplication.  Only
	-- ulong MUST be defined this way.  The others are
	-- defined similarly due only to aesthetics.
	type ubyte is mod 2**8;   --(1-byte)  0..255
	type ushort is mod 2**16; --(2-bytes) 0..65535
	type ulong is mod 2**64;  --(8-bytes)

	usmx : constant ushort := 65535;
	ubmx : constant ubyte := 255;

	maxrows : constant ushort := 20;
	maxcols : constant ushort := 25;
	maxsize : constant ushort := maxrows*maxcols; -- 500


	subtype interange is ushort range 1..maxsize; -- 1..500

	type booltype is array(interange) of boolean; --500 bytes

	type pooltype is array(ubyte) of boolean; -- 256 bytes
	pragma pack(pooltype); -- 32 bytes (16jul19)

	type vfstype is array(ubyte) of ubyte;     --1*256 bytes
	pragma pack( vfstype );

	type vftype is array(interange) of ubyte;  --1*500 bytes
	type vstype is array(interange) of ushort; --2*500 bytes


	type keytype is 
	record
		suma, sumb,sumc : ulong;
		pulkey     : ubyte;
	end record;

	type hashrectype is
	record
		xlevel: ubyte := 0;
		ngoals,
		prsave, pcsave, prevmove, boxpull : ubyte; --5
		totmovz,totpulz: ushort; --4
		vfsave : pooltype := (others=>false);  -- 32 bytes
		prevkey : keytype;  -- 25
	end record; -- old:290 bytes
	pragma pack(hashrectype); --66 bytes



	function "<" (k1, k2: in keytype ) return boolean;
	function ">" (k1, k2: in keytype ) return boolean;

	package mysplay is new splaylist( keytype, hashrectype, "<", ">" );
	use mysplay;


	mytree : mysplay.listtype;
	status : mysplay.statustype; -- Ok, found, ...


	win_suma, win_sumb, win_sumc : ulong := 0;
	bwin_pulkey, pwin_pulkey : ubyte := 0;
	bwin_key, pwin_key : keytype;


	careful,
	relent, urgent, desperate, dying, winner : boolean := false;

	nbvalid : integer := 0;

	bvalid, pvalid: booltype; --1nov18

	pfff,hfff,
	ff, ovf, vf, nappch : vftype;

	xtunn, nexus, bnexus, enexus : booltype := (others=>false);

	urgency: ubyte := 0; --increases as needed

	relenting, --increases as needed
	bestnk : ushort := 0;
	nk, ng: ushort;
	gpr, gpc : ushort := usmx; --0;


	ee : vstype := (others=>usmx);
	-- ee is an array(1..20*25) of ushort
	-- has values in 0..255 for feasible box positions...
	-- ee=usmx=65535 elsewhere.  This array is defined
	-- within readpuzzle.





	savefp, gngoals : ushort := 0;

	ncols, nrows : ushort;

	pfmax : ushort := 0;

	grow,gcol,
	prfinal, pcfinal : array(interange) of ushort;
	pr, pc : ushort;

	maxbx : constant ushort := 24;
	type etype is array(1..maxbx) of ubyte;


	level, maxlevel : integer;

	infilname : unbounded_string;




procedure bitrep(
	nb : ushort; -- 1..24
	e  : etype; -- array(1..24) of 0..255
	suma, sumb, sumc : in out ulong );

function indx(r,c : ushort) return ushort;







function psetwinkey( wpkey: ubyte ) return keytype;


function ptestleft return boolean;
function ptestright return boolean;
function ptestdown return boolean;
function ptestup return boolean;




function ignore_this_line( line : string; len:natural ) return boolean;

procedure readPuzzle( lvl1: integer );



procedure prestore( rec : hashrectype );


function trimmed_int( i: integer ) return unbounded_string;


procedure pdocument(
	fout: text_io.file_type;
	key : keytype;
	nmoves, bmoves : in out integer );


procedure pwinnertest( key: keytype; tpulz, tmovz: ushort );

function min(a,b: ushort) return ushort;



procedure pcountbest( k,g : in out ushort );

procedure pdump;



procedure psaveifnew( 
	okey: keytype; 
	pmove, 
	olp,olm, 
	boxpulls,moves : ushort );

procedure psave0;
procedure bsave0;

procedure bsaveifnew( 
	okey: keytype;
	pmove,
	olpulz,
	boxpulls : ushort;
	pr,pc, br,bc: ushort
	);






------------- ibox below this line -------------------------

	-- structs for Dynamic Programming relaxation [flood-fill]
	fff, bestpred, bestcost : vftype;

	hbestcost,pbestcost : vstype;

	htunl,vtunl : booltype := (others=>false);
	corral,
		hviano,hviaso,hviaea,hviawe,
		pviano,pviaso,pviaea,pviawe,
		viano, viaso, viaea, viawe,
		cviano, cviaso, cviaea, cviawe : booltype;

	usinf  : constant ushort := 9999;
	ubinf  : constant ubyte := ubmx-1; 
	--254 (ubinf+1 must be a valid ubyte)

	fromno: constant ubyte := 0;
	fromso: constant ubyte := 1;
	fromea: constant ubyte := 2;
	fromwe: constant ubyte := 3;
	none  : constant ubyte := ubinf; --254





procedure bwinnertest( key: keytype;  tpulz: ushort );


function bsetwinkey( wpkey: ubyte ) return keytype;




procedure brestore( rec : hashrectype;  pr,pc : out ushort );
procedure bdump(pr,pc: ubyte);

procedure bdocument(
	fout: text_io.file_type;
	key : keytype;
	nmoves, bmoves : in out ushort;
	firstcall: boolean
	);


function btestleft(br,bc:ushort) return boolean;
function btestright(br,bc:ushort) return boolean;
function btestdown(br,bc:ushort) return boolean;
function btestup(br,bc:ushort) return boolean;



ppath : array(1..ubmx) of character;

function dppathexists( r1,c1 : ushort ) return boolean;
procedure dppath( r1,c1 : ushort;  np: out ubyte );

procedure initwdpcorral;
procedure initdpcorral;
procedure dpcorral(
	r0,c0 : ushort; --puller.pos
	ulkey : out ubyte -- 3rd component of keytype
	);
procedure dpwcorral(
	r0,c0 : ushort; --puller.pos
	ulkey : out ubyte -- 3rd component of keytype
	);
procedure dppathprep(
	r0,c0 : ushort --puller.pos
	);
procedure initdp;


procedure checkForUserFile( ok: out boolean );

procedure findnexii;

procedure countbest( k,g : in out ushort );

procedure dpbox;
procedure dppuller;
procedure remdead;

procedure dumpvalid;


end utils; --package

