Pascal Translation Notes

Python → Free Pascal / Lazarus — 3D Knight’s Tour

EDM Health Services · NABS Biomedical Platform


1. Files Delivered

File Description Run with
knights_tour_3d.pas Console version — ASCII board, full tour fpc knights_tour_3d.pas./knights_tour_3d
knights_tour_gui.pas Lazarus GUI unit — graphical board Lazarus IDE or lazbuild
knights_tour_gui.lpr Lazarus project entry point lazbuild knights_tour_gui.lpr

2. Installing Free Pascal / Lazarus

Free Pascal (console only)

# Ubuntu / Debian
sudo apt install fpc

# macOS (Homebrew)
brew install fpc

# Windows
# Download from https://www.freepascal.org/download.html

Lazarus IDE (GUI version)

# Ubuntu / Debian
sudo apt install lazarus

# macOS
# Download from https://www.lazarus-ide.org/

# Windows
# Download combined FPC+Lazarus installer from lazarus-ide.org

Compile console version

fpc knights_tour_3d.pas -O2
./knights_tour_3d          # Linux/Mac
knights_tour_3d.exe        # Windows

3. Python → Pascal Translation Table

3.1 Data Types

Python Pascal (Free Pascal) Notes
@dataclass RECORD Pascal records are value types
list[TPos] TPosArray = array of TPos Dynamic array
set() ARRAY OF BOOLEAN Boolean grid is O(1) lookup
dict[str,int] RECORD or ARRAY Use typed arrays when keys are known
Optional[T] T + Found: Boolean Pass Found as out parameter
int Integer 32-bit signed
float Double 64-bit IEEE 754
str AnsiString (with {$H+}) Pascal strings are 1-indexed
bool Boolean True / False
None Depends on type Use sentinel value or Found flag
Enum (gpSetup, gpPlaying, gpResults) Pascal enumerated type

3.2 Control Flow

Python Pascal
for i in range(n): for i := 0 to n-1 do
for x in list: for i := 0 to Length(list)-1 do then list[i]
while True: repeat ... until False; or while True do
break Break
continue Continue
if x is None: if not Found then or sentinel check
pass { nothing } or dummy begin end
try/except try ... except ... end

3.3 Functions and Procedures

Python Pascal
def foo() -> None: procedure Foo;
def foo() -> int: function Foo: Integer;
return x Result := x (preferred) or Foo := x
def foo(x: int = 5): Two overloaded procedures (no defaults in TP/FPC)
*args Not directly supported — use array parameter
lambda x: x*2 Inline function or local nested function
out param var Param or out Param (FPC extension)

3.4 Classes

Python Pascal (Object Pascal)
class Foo: TFoo = class(TObject)
def __init__(self): constructor Create(AOwner...);
def __del__(self): destructor Destroy; override;
self.x FX (F-prefix convention for private fields)
@property property X: T read FX write FX;
isinstance(x, T) x is T
super().__init__() inherited Create(...)

3.5 Dynamic Arrays

{ Python: path = [] }
var Path : TPosArray;   { declared, Length = 0 }

{ Python: path.append(pos) }
SetLength(Path, Length(Path)+1);
Path[Length(Path)-1] := Pos;

{ Python: len(path) }
Length(Path)

{ Python: path[0:5] }
{ Pascal: must copy manually or use slice pointer tricks }

{ Python: del path[-1] }
SetLength(Path, Length(Path)-1);

3.6 String Operations

{ Python: f"({r}, {c})" }
Format('(%d, %d)', [R, C])

{ Python: str(n) }
IntToStr(N)

{ Python: float(s) }
StrToFloat(S)   { raises exception on error }
StrToFloatDef(S, 0.0)   { returns default on error }

{ Python: s.upper() }
UpperCase(S)

{ Python: s.strip() }
Trim(S)

{ Python: ','.join(list) }
{ Pascal: manual loop with string concatenation }

3.7 Math

{ Python: import math / import random }
uses Math, SysUtils;

{ Python: random.random() }
Random   { returns 0.0 <= x < 1.0 }

{ Python: random.randint(0, n-1) }
Random(N)   { returns 0 <= x < N }

{ Python: random.shuffle(list) }
{ Pascal: Fisher-Yates — see ShuffleIntArray in console source }

{ Python: math.min(a, b) }
Min(A, B)   { from Math unit }

{ Python: math.floor(x) }
Trunc(X)    { or Floor(X) from Math }

{ Python: round(x) }
Round(X)    { banker's rounding in Pascal — watch for .5 cases }

4. Key Algorithm Translations

4.1 Visited Set

# Python — hash set, O(1)
visited: Set[Tuple] = set()
visited.add((r, c, l))
if (r, c, l) in visited:
{ Pascal — boolean grid, O(1), faster and type-safe }
Visited : array of array of array of Boolean;
Visited[L][R][C] := True;
if Visited[L][R][C] then

4.2 Valid Moves

# Python
def valid_moves(pos, visited, rows, cols, levels):
    r, c, l = pos
    return [(r+dr, c+dc, l+dl)
            for dr, dc, dl in KNIGHT_MOVES_3D
            if 0<=r+dr<rows and 0<=c+dc<cols
               and 0<=l+dl<levels
               and (r+dr,c+dc,l+dl) not in visited]
{ Pascal }
function CountMoves(const Pos: TPos; const Vis: TBoolGrid): Integer;
var i, nr, nc, nl : Integer;
begin
  Result := 0;
  for i := 0 to MOVE_COUNT-1 do
  begin
    nr := Pos.R + KnightMoves[i].DR;
    nc := Pos.C + KnightMoves[i].DC;
    nl := Pos.L + KnightMoves[i].DL;
    if InBounds(nr,nc,nl) and not Vis[nl][nr][nc] then
      Inc(Result);
  end;
end;

4.3 Warnsdorff’s Rule

# Python — list comprehension + min()
return min(candidates,
           key=lambda p: len(valid_moves(p, visited|{p},
                                         rows, cols, levels)))
{ Pascal — explicit loop, same O(24²) complexity }
BestScore := MaxInt;
for j := 0 to NCands-1 do
begin
  i := Cands[Shuffled[j]];
  Next := ...;
  Vis[Next.L][Next.R][Next.C] := True;   { temporarily mark }
  Score := CountMoves(Next, Vis);
  Vis[Next.L][Next.R][Next.C] := False;  { unmark }
  if Score < BestScore then
  begin
    BestScore := Score;
    Result    := Next;
    Found     := True;
  end;
end;

4.4 Color Grid Initialization

# Python
self.board = [
    [[random.choice(COLOR_NAMES) if random.random() < 0.22 else None
      for _ in range(cols)]
     for _ in range(rows)]
    for _ in range(levels)]
{ Pascal }
procedure InitBoardColors(var Colors: TColorGrid; const Cfg: TConfig);
var l, r, c : Integer;
begin
  SetLength(Colors, Cfg.Levels);
  for l := 0 to Cfg.Levels-1 do
  begin
    SetLength(Colors[l], Cfg.Rows);
    for r := 0 to Cfg.Rows-1 do
    begin
      SetLength(Colors[l][r], Cfg.Cols);
      for c := 0 to Cfg.Cols-1 do
        if Random(100) < 20 then Colors[l][r][c] := Random(COLOR_COUNT)
        else                     Colors[l][r][c] := -1;  { -1 = no color }
    end;
  end;
end;

5. GUI Translation (pygame → Lazarus LCL)

pygame Lazarus LCL
pygame.Surface TBitmap or TPaintBox.Canvas
pygame.Rect TRect
pygame.draw.rect(surf,col,rect) Canvas.Brush.Color:=col; Canvas.FillRect(rect)
pygame.draw.circle(surf,col,ctr,r) Canvas.Ellipse(x-r,y-r,x+r,y+r)
pygame.draw.line(surf,col,p1,p2) Canvas.MoveTo(p1); Canvas.LineTo(p2)
pygame.font.render(txt,True,col) Canvas.Font.Color:=col; Canvas.TextOut(x,y,txt)
pygame.time.Clock.tick(fps) TTimer.Interval := 1000 div fps
pygame.event.get() TForm.OnMouseDown, TForm.OnKeyDown etc.
pygame.display.flip() TPaintBox.Invalidate (triggers OnPaint)
pygame.Color(r,g,b) RGBToColor(r,g,b) or RGB(r,g,b) macro
SRCALPHA surface TBitmap.PixelFormat := pf32bit + alpha handling

6. Compiler Directives Reference

{$MODE OBJFPC}    { Enable Object Pascal with Free Pascal extensions }
{$H+}             { Use AnsiString (heap-allocated) not ShortString }
{$RANGECHECKS ON} { Catch array out-of-bounds at runtime (debug) }
{$RANGECHECKS OFF}{ Turn off for production build (faster)        }
{$O+}             { Optimize (same as -O2 on command line)         }
{$IFDEF WINDOWS}  { Conditional compilation for Windows            }
{$IFDEF UNIX}     { Conditional compilation for Linux/Mac          }

7. GitHub Module Structure

nabs-platform/
├── python/
│   ├── knights_tour_3d.py        ← Phase 1 template (DONE)
│   └── requirements.txt
├── browser/
│   ├── knights_tour_browser.html ← Browser game (DONE)
│   └── nabs_demo.html            ← NABS UI demo (DONE)
├── pascal/
│   ├── knights_tour_3d.pas       ← Console version (DONE)
│   ├── knights_tour_gui.pas      ← Lazarus GUI unit (DONE)
│   ├── knights_tour_gui.lpr      ← Lazarus project file (DONE)
│   └── PASCAL_NOTES.md           ← This file (DONE)
├── cpp/                          ← Phase 3 (next)
│   ├── knights_tour_3d.cpp
│   └── CMakeLists.txt
├── THEORY.md                     ← WFFs, predicate calculus (DONE)
└── README.md                     ← Project overview (DONE)

EFE Health Systems · NABS Platform · Toledo, Ohio Pascal implementation complete — C++ Phase 3 next