MODULE Disk; IMPORT Cell, Hole, RealCell, Files, TextRider, Strings, Out; CONST Size = 16; TYPE P* = POINTER TO T; T* = RECORD cells : ARRAY Size OF Cell.P; rotCount : INTEGER; next : P; END; (* T *) PROCEDURE ( d : P ) ReadCell* ( reader : TextRider.Reader ) : Cell.P; END ReadCell; PROCEDURE ( d : P ) WriteCellNum* ( index : INTEGER ); BEGIN IF d.cells [ index ] IS Hole.P THEN d.next.WriteCellNum ( index ); ELSE d.cells [ index ].WriteNum; END; (* IF *) END WriteCellNum; PROCEDURE ( d : P ) WriteAllCellNum*; VAR i : INTEGER; BEGIN FOR i := 0 TO Size - 1 DO d.WriteCellNum ( i ); END; (* FOR *) Out.Ln; END WriteAllCellNum; PROCEDURE ( d : P ) GetText* ( index : INTEGER; VAR text : ARRAY OF CHAR ); BEGIN IF d.cells [ index ] IS Hole.P THEN d.next.GetText ( index, text ); ELSE d.cells [ index ].GetText ( text ); END; (* IF *) END GetText; PROCEDURE ( d : P ) CheckText* ( good : ARRAY OF CHAR ) : BOOLEAN; VAR curText : ARRAY Size * RealCell.MaxLength OF CHAR; text : ARRAY RealCell.MaxLength OF CHAR; i : INTEGER; BEGIN Strings.Assign ( "", curText ); FOR i := 0 TO Size - 1 DO d.GetText ( i, text ); Strings.Append ( text, curText ); END; (* FOR *) RETURN curText = good; END CheckText; PROCEDURE ( d : P ) GetColors* ( index : INTEGER; VAR colors : ARRAY OF CHAR ); BEGIN IF d.cells [ index ] IS Hole.P THEN d.next.GetColors ( index, colors ); ELSE d.cells [ index ].GetColors ( colors ); END; (* IF *) END GetColors; PROCEDURE ( d : P ) CheckColors* () : BOOLEAN; VAR curColors : ARRAY Size * RealCell.MaxColors OF CHAR; colors : ARRAY RealCell.MaxColors OF CHAR; i, j : INTEGER; BEGIN Strings.Assign ( "", curColors ); FOR i := 0 TO Size - 1 DO d.GetColors ( i, colors ); Strings.Append ( colors, curColors ); END; (* FOR *) FOR i := 0 TO Strings.Length ( curColors ) - 1 DO FOR j := i + 1 TO Strings.Length ( curColors ) - 1 DO IF curColors [ i ] = curColors [ j ] THEN RETURN FALSE; END; (* IF *) END; (* FOR *) END; (* FOR *) RETURN TRUE; END CheckColors; PROCEDURE ( d : P ) Rotate* () : BOOLEAN; VAR c : Cell.P; i : INTEGER; BEGIN c := d.cells [ 0 ]; FOR i := 1 TO Size - 1 DO d.cells [ i - 1 ] := d.cells [ i ]; END; (* FOR *) d.cells [ Size - 1 ] := c; INC ( d.rotCount ); IF d.rotCount = Size THEN d.rotCount := 0; IF d.next # NIL THEN RETURN d.next.Rotate (); ELSE RETURN FALSE; END; (* IF *) ELSE RETURN TRUE; END; (* IF *) END Rotate; PROCEDURE Init* ( d : P; next : P; fileName : ARRAY OF CHAR ); VAR f : Files.File; error : INTEGER; r : TextRider.Reader; line : ARRAY 256 OF CHAR; cell : Cell.P; n : INTEGER; BEGIN d.next := next; d.rotCount := 0; f := Files.Old ( fileName, { 0 }, error ); NEW ( r ); TextRider.InitReader ( r, f ); n := 0; REPEAT cell := d.ReadCell ( r ); IF cell # NIL THEN d.cells [ n ] := cell; INC ( n ); END; (* IF *) UNTIL cell = NIL; f.Close; END Init; END Disk.