Version$/"Chess Opening Rule Generator V1.0a"
! Program to read final positions of opening book sequences,
! along with evaluations, and try to formulate rules,
! using the technique outlined in PAMI-7,
! "Conceptual Clustering in Knowledge Organization".
!
Dim DontCare/:FF/,WhitePiece/:8/,BlackPiece/:10/
Dim PieceName$/"..WPWNWRWrWBWQWkWK..BPBNBRBrBBBQBkBK"/
Dim Rule$(66)
Dim Rules$[500](66)
Dim Rules/1/,Output/2/

Subroutine DisplayBoard(Board$)
! Subroutine to take 68-byte string and display as Chess board pattern
! Byte 1 is SideToMove flag
! Bytes 2-65 are ChessBoard
! Byte 66 is the evalution
! A code of $FF in a byte means "DON'T CARE" (printed as "x" for square)
!
  Print "Side To Move ";
  If Board$(1)=DontCare
  Then Print "Either";
  ElseIf Board$(1)=WhitePiece
  Then Print "White";
  Else Print "Black";
  Print "     Evaluation: ";
  If Board$(66)=DontCare
  Then Print "NO PREDICTION"
  Else Print Board$(66)-128
  For Row=0 to 7
      Print Using "# ",Row+1;
      For Column=0 to 7
          Piece=Board$(Row*8+Column+2)
          If Piece=DontCare
          Then Print "x  ";
          Else Print PieceName$[Piece,2];" ";
      Next Column
      Print
  Next Row
  Print "  a  b  c  d  e  f  g  h"
  Print
  Return Subroutine
End

Subroutine FetchRules
! Subroutine to read rules from a file
   Input "Fetch rules from where? " Line$
   Open #Rules,Line$
   NumberOfRules=0
CollectRules: ...
&  Repeat
      Read #Rules,Rule$ \ ! Fetch a rule from the file
      If EOF(Rules) Then Exit CollectRules
      DisplayBoard(Rule$) \ ! Show our master what we read
      NumberOfRules=NumberOfRules+1
      Rules$(NumberOfRules)=Rule$ \ ! Stash rule away
   End
   Print NumberOfRules;"read from file."
   Return Subroutine
End

Def Distance(Rule1,Rule2)
! Function that returns the distance between two rules
! Note that NO use of concept heirarchies is made...i.e., a Bishop is
! closer to a Queen in function on a diagonal than a Knight.
   Let Dist=Rules$(Rule1)[1]<>Rules$(Rule2)[1]
   For Square=2 to 65
       Let Dist=Dist+( Rules$(Rule1)[Square]<>Rules$(Rule2)[Square] )
   Next Square
   Let Dist=Dist+Rules$(Rule1)[66]<>Rules$(Rule2)[66]
   Return Dist
End

Subroutine FormStars
! Subroutine to build "stars" from rules in Rules$
   For RuleNumber=1 to NumberOfRules
       ! For each rule...
       Let MinDistance=Infinity \ ! Start with high value
       For RuleScan=RuleNumber+1 to NumberOfRules
           ! Check all the other rules to see which rules are closest
           let i=Distance(RuleNumber,RuleScan)
           If i<MinDistance Then MinDistance=i \ ! Record closest distance
       Next RuleScan
       For RulesScan=RuleNumber+1 to NumberOfRules
           ! Collapse rules whose distance is MinDistance
           If MinDistance=Distance(RuleNumber,RuleScan)
           Then
               ! Collapse rules by generalizing NOT EQUAL to ANY
               For i=1 to len(Rule$)
                   If Rules$(RuleNumber)(i)=DontCare Then Cycle i
                   If Rules$(RuleNumber)(i)<>Rules$(RuleScan)(i)
                   Then Rules$(RuleNumber)(i)=DontCare
               Next i
           Fi
       Next RuleScan
   Next RuleNumber
   Return Subroutine
End
!^L
MainProgram:
    FetchRules
    FormStars
UNFINISHED
    DisplayRules
    Exit
End
