[Xotcl] Simple example: TicTacToe

Rick Hedin rhedin@aquifer.geology.uiuc.edu
Mon, 12 Mar 2001 16:44:20 -0600


This is a multi-part message in MIME format.

------=_NextPart_000_0000_01C0AB13.AFA0C050
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit


Hello all.

I was having some trouble understanding basic things about XOTcl.  I found
an old TicTacToe program written in OTcl (by Gustaf?) and translated it so
it would run on Tk rather than Mofe.  It's self-contained, involves several
cooperating objects, and has a simple domain.  Maybe some other beginner
would find going through it useful.

I have attached the script to this mail message.


	Regards,

	Rick

------=_NextPart_000_0000_01C0AB13.AFA0C050
Content-Type: application/octet-stream;
	name="tictactoe.xot"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="tictactoe.xot"

#!/usr/bin/X11/mofe --f=0A=
=0A=
set seed [pid]=0A=
proc random nvalues {=0A=
  global seed=0A=
  set seed [expr ($seed*12731+34197)%21473]=0A=
  return [expr $seed%$nvalues]=0A=
}=0A=
=0A=
wm iconify . =0A=
=0A=
# It seems as though topLevel is a special motif keyword.  I've replaced =
it, =0A=
# wherever it occurs, with .top .  =0A=
toplevel .top=0A=
=0A=
=0A=
Class TicTacToe=0A=
=0A=
TicTacToe instproc init {parent} {=0A=
=0A=
if 0 {  ;# I don't think fallback resources are necessary. =0A=
  fallbackResources topLevel \=0A=
      *XmPushButton*fontList -*-helvetica-medium-r-normal-*-14-*-*-* \=0A=
      *msgArea.background turquoise \=0A=
      *msgArea.foreground black \=0A=
      *XmPushButton*background gray90 \=0A=
      *commandArea.background turquoise \=0A=
      *gameBoard.background turquoise=0A=
}=0A=
=0A=
  Engine engine=0A=
  # XmForm form $parent=0A=
  frame $parent.form=0A=
  # XmSeparator sep form  ;# I don't think we need a separator. =0A=
  # Message msgArea form=0A=
  Message msgArea $parent.form=0A=
  # Command commandArea form=0A=
  Command commandArea $parent.form=0A=
  # GameBoard gameBoard form=0A=
  GameBoard gameBoard $parent.form=0A=
  pack $parent.form=0A=
=0A=
  # sV gameBoard \                      ;# The 1st, 3rd and 4th sV just =0A=
  #     topAttachment    ATTACH_FORM \  ;# position the elements. =0A=
  #     leftAttachment   ATTACH_FORM \=0A=
  #     rightAttachment  ATTACH_FORM \=0A=
  #     bottomWidget     sep         \=0A=
  #     bottomAttachment ATTACH_WIDGET=0A=
=0A=
  # sV sep \                            ;# This 2nd one is just not =
necessary. =0A=
  #     topAttachment    ATTACH_NONE \=0A=
  #     leftAttachment   ATTACH_FORM \=0A=
  #     rightAttachment  ATTACH_FORM \=0A=
  #     bottomWidget     msgArea     \=0A=
  #     bottomAttachment ATTACH_WIDGET=0A=
=0A=
  # sV msgArea \=0A=
  #     topAttachment    ATTACH_NONE  \=0A=
  #     leftAttachment   ATTACH_FORM  \=0A=
  #     rightAttachment  ATTACH_FORM  \=0A=
  #     bottomWidget     commandArea  \=0A=
  #     bottomAttachment ATTACH_WIDGET=0A=
=0A=
  # sV commandArea \=0A=
  #     topAttachment    ATTACH_NONE \=0A=
  #     leftAttachment   ATTACH_FORM \=0A=
  #     rightAttachment  ATTACH_FORM \=0A=
  #     bottomAttachment ATTACH_FORM=0A=
=0A=
  pack $parent.form.gameBoard -side top -fill x -expand 1 =0A=
  pack $parent.form.msgArea   -side top -fill x -expand 1 =0A=
  pack $parent.form.commandArea -side top -fill x -expand 1 =0A=
=0A=
}=0A=
=0A=
# It seems to me that sV combines the characteristics of pack (here) and =0A=
# of config (below). =0A=
# =0A=
# I guess packing can be regard as a variety of attribute. =0A=
=0A=
=0A=
#************************************************************************=
******=0A=
# GameBoard Class=0A=
#************************************************************************=
******=0A=
Class GameBoard=0A=
=0A=
GameBoard instproc init {passedParent} {=0A=
  [self] instvar grid  ;# Replaced all occurrences of $self with [self]. =0A=
  [self] instvar parent=0A=
  set parent $passedParent=0A=
  set gridsize 100=0A=
=0A=
  # XmRowColumn gameBoard $parent \=0A=
  #     numColumns  3 \=0A=
  #     packing	  PACK_COLUMN \=0A=
  #     adjustLast  FALSE=0A=
  # =0A=
  # for {set i 0} {$i < 9} {incr i} {=0A=
  #   set grid($i) [XmDrawnButton xo gameBoard \=0A=
  # 		      userData	        $i \=0A=
  # 		      recomputeSize     FALSE \=0A=
  # 		      width	        $gridsize \=0A=
  # 		      height	        $gridsize \=0A=
  # 		      labelType         pixmap \=0A=
  # 		      activateCallback  "engine recordMove %U" ]=0A=
  #   [self] activateSquare $i=0A=
  # }=0A=
  # I don't believe the userData is ever used. =0A=
  # Hm.  Maybe %U gives the user data.  =0A=
=0A=
  frame $parent.gameBoard=0A=
=0A=
  for {set i 0} {$i < 3} {incr i} {=0A=
=0A=
    set grid($i) [button $parent.gameBoard.b$i \=0A=
     -image N -width $gridsize -height $gridsize \=0A=
     -command "engine recordMove $i"]=0A=
    set grid([expr $i + 3]) [button $parent.gameBoard.b[expr $i + 3] \=0A=
     -image N -width $gridsize -height $gridsize \=0A=
     -command "engine recordMove [expr $i + 3]"]=0A=
    set grid([expr $i + 6]) [button $parent.gameBoard.b[expr $i + 6] \=0A=
     -image N -width $gridsize -height $gridsize \=0A=
     -command "engine recordMove [expr $i + 6]"]=0A=
    [self] activateSquare $i=0A=
    [self] activateSquare [expr $i + 3]=0A=
    [self] activateSquare [expr $i + 6]=0A=
=0A=
    grid $grid($i) $grid([expr $i + 3]) $grid([expr $i + 6])=0A=
=0A=
  }=0A=
}=0A=
=0A=
# Okay.  So this is what the grid array is.  9 buttons, to be arranged =0A=
# in a 3x3 grid. =0A=
# =0A=
# In this XmDrawnButton syntax, I wonder if xo is the name of the =
button, =0A=
# and gameBoard is the button's parent.  Like XmRowColumn gameBoard =
$parent. =0A=
# Or XmSeparator sep form, or XmForm form $parent (<--topLevel). =0A=
# =0A=
# gameBoard is both instantiated as a class and as a widget.  This =
appears =0A=
# to be their method of hooking together widgets and classes.  =0A=
#         GameBoard gameBoard form=0A=
#         XmRowColumn gameBoard $parent=0A=
# I wonder if they are kept distinct by context, or OTcl has an =
automatic =0A=
# "Well, that didn't work; let's try interpreting it as a widget" =
feature. =0A=
# =0A=
# Have changed all occurrences of -bitmap to -image, because I couldn't =0A=
# figure out how to create a non-predefined bitmap. =0A=
=0A=
=0A=
GameBoard instproc markSquare {position value} {=0A=
  [self] instvar grid=0A=
  [self] deactivateSquare $position=0A=
  # sV $grid($position) labelPixmap $value alignment alignment_center=0A=
  $grid($position) config -image $value=0A=
  # We plan to do the center alignment when the buttons are created and =
gridded.=0A=
}=0A=
=0A=
GameBoard instproc clear {} {=0A=
  [self] instvar grid=0A=
  foreach i [array names grid] {=0A=
    [self] activateSquare $i=0A=
  }=0A=
}=0A=
=0A=
GameBoard instproc activateSquare {position} {=0A=
  [self] instvar grid =0A=
  # sV $grid($position) \=0A=
  #     pushButtonEnabled  TRUE \=0A=
  #     shadowType         SHADOW_OUT \=0A=
  #     shadowThickness    2 \=0A=
  #     highlightColor     white \=0A=
  #     labelPixmap        Unspecified=0A=
  $grid($position) config -state normal -relief raised -borderwidth 2 \=0A=
   -highlightcolor white -image N =0A=
  # I am unsure about highlightcolor, even though the name is the same. =0A=
}=0A=
=0A=
GameBoard instproc deactivateSquare {position} {=0A=
  [self] instvar grid =0A=
  # sV $grid($position) \=0A=
  #     pushButtonEnabled  FALSE \=0A=
  #     shadowType         SHADOW_IN \=0A=
  #     highlightColor     gray90=0A=
  $grid($position) config -state disabled -relief sunken -highlightcolor =
gray90=0A=
}=0A=
=0A=
GameBoard instproc highlightSquare {position} {=0A=
  [self] instvar grid =0A=
  # sV $grid($position) \=0A=
  #     shadowType         SHADOW_ETCHED_OUT \=0A=
  #     shadowThickness    10=0A=
  $grid($position) config -relief groove -borderwidth 10=0A=
}=0A=
=0A=
GameBoard instproc deemphasizeSquare {position} {=0A=
  [self] instvar grid =0A=
  # sV $grid($position) shadowThickness 0=0A=
  $grid($position) config -borderwidth 0 =0A=
}=0A=
#************************************************************************=
******=0A=
# Message Class=0A=
#************************************************************************=
******=0A=
Class Message=0A=
=0A=
Message instproc init {passedParent} {=0A=
  [self] instvar parent=0A=
  set parent $passedParent=0A=
  # XmLabel msgArea $parent \=0A=
  #     labelString " " recomputeSize 0=0A=
  label $parent.msgArea -text " " =0A=
  [self] postMessage ""=0A=
}=0A=
=0A=
Message instproc postMessage {message} {=0A=
  [self] instvar parent=0A=
  # sV msgArea labelString $message=0A=
  $parent.msgArea config -text "$message"=0A=
  # Apparently in motif, a widget has a unique name throughout the =
widget tree, =0A=
  # and the widget knows who its parent is. =0A=
}=0A=
=0A=
Message instproc postAlert {{message {}}} {=0A=
  if ![string match $message {}] {=0A=
    [self] postMessage $message=0A=
  }=0A=
  bell=0A=
}=0A=
#************************************************************************=
******=0A=
# Command Class=0A=
#************************************************************************=
******=0A=
Class Command=0A=
=0A=
Command instproc init {parent} {=0A=
  # XmForm commandArea $parent  ;# I say it's a kind of frame. =0A=
  frame $parent.commandArea=0A=
  # XmPushButton newGame commandArea \=0A=
  #     topOffset        5 \=0A=
  #     bottomOffset     5 \=0A=
  #     leftOffset       5 \=0A=
  #     topAttachment    ATTACH_FORM \=0A=
  #     leftAttachment   ATTACH_FORM \=0A=
  #     rightAttachment  ATTACH_NONE \=0A=
  #     bottomAttachment ATTACH_FORM \=0A=
  #     labelString      "new" \=0A=
  #     activateCallback "[self] newGameCallback"=0A=
  button $parent.commandArea.newGame -text new -command "[self] =
newGameCallback"=0A=
  pack $parent.commandArea.newGame -side left=0A=
  # XmPushButton quit commandArea \=0A=
  #     topOffset        5 \=0A=
  #     bottomOffset     5 \=0A=
  #     rightOffset      5 \=0A=
  #     topAttachment    ATTACH_FORM \=0A=
  #     leftAttachment   ATTACH_NONE \=0A=
  #     rightAttachment  ATTACH_FORM \=0A=
  #     bottomAttachment ATTACH_FORM \=0A=
  #     activateCallback "[self] quitCallback"=0A=
  button $parent.commandArea.quit -text quit -command "[self] =
quitCallback"=0A=
  pack $parent.commandArea.quit -side right=0A=
}=0A=
=0A=
Command instproc newGameCallback {} {=0A=
  engine reset=0A=
}=0A=
=0A=
Command instproc quitCallback {} {=0A=
  # quit  ;# Why did I have to change quit to exit?  Did quit by some =0A=
          ;# mysterious alchemy refer to Engine::quit?  =0A=
          ;# No.  Engine::reset took an explicit reference. =0A=
          ;# I suppose quit could have been a mofe keyword. =0A=
  exit=0A=
}=0A=
#************************************************************************=
******=0A=
# Engine Subsystem=0A=
#************************************************************************=
******=0A=
#************************************************************************=
******=0A=
# Board Class=0A=
#************************************************************************=
******=0A=
Class Board=0A=
=0A=
Board instproc init {} {=0A=
  [self] instvar winningBits=0A=
  set winningBits(0) 1..1..1..=0A=
  set winningBits(1) .1..1..1.=0A=
  set winningBits(2) ..1..1..1=0A=
  set winningBits(3) 111......=0A=
  set winningBits(4) ...111...=0A=
  set winningBits(5) ......111=0A=
  set winningBits(6) 1...1...1=0A=
  set winningBits(7) ..1.1.1..=0A=
  [self] clear=0A=
}=0A=
=0A=
Board instproc winningSquares {} {=0A=
  [self] instvar winningPattern=0A=
  return [split $winningPattern {}]=0A=
}=0A=
=0A=
Board instproc clear {} {=0A=
  [self] instvar state=0A=
  set state NNNNNNNNN=0A=
}=0A=
=0A=
Board instproc recordMove {position mark} {=0A=
  [self] instvar state=0A=
  if ![string match [string index $state $position] N] {=0A=
    return ILLEGALMOVE=0A=
  }=0A=
  set last [expr $position - 1]=0A=
  set state [string range $state 0 [expr $position - 1]]$mark[string =
range \=0A=
	 $state [expr $position + 1] end]=0A=
  return VALIDMOVE=0A=
}=0A=
=0A=
Board instproc pattern {} {=0A=
  [self] instvar state=0A=
  return $state=0A=
}=0A=
=0A=
Board instproc isVacant {position} {=0A=
  [self] instvar state=0A=
  string match [string index $state $position] N=0A=
}=0A=
=0A=
Board instproc freeSquares {{list {0 1 2 3 4 5 6 7 8}}} {=0A=
  [self] instvar state=0A=
  foreach position $list {=0A=
    if [string match [string index $state $position] N] {=0A=
      lappend freelist $position=0A=
    }=0A=
  }=0A=
  return $freelist=0A=
}=0A=
=0A=
Board instproc numFreeSquares {{list {0 1 2 3 4 5 6 7 8}}} {=0A=
  [self] instvar state=0A=
  set count 0=0A=
  foreach position $list {=0A=
    if [string match [string index $state $position] N] {=0A=
      incr count=0A=
    }=0A=
  }=0A=
  return $count=0A=
}=0A=
=0A=
Board instproc whoHasWon {} {=0A=
  [self] instvar winningBits state winningPattern=0A=
  for {set i 0} {$i < 8} {incr i} {=0A=
    regsub -all {\.} $winningBits($i) 0 winningPattern=0A=
    regsub -all 1 $winningBits($i) O player=0A=
    if [regexp $player $state] {=0A=
      return O=0A=
    }=0A=
    regsub -all 1 $winningBits($i) X player=0A=
    if [regexp $player $state] {=0A=
      return X=0A=
    }=0A=
  }=0A=
  if [[self] numFreeSquares]>0 {=0A=
    return N=0A=
  }=0A=
  return TIE=0A=
}=0A=
#************************************************************************=
******=0A=
# MoveGenerator Class=0A=
#************************************************************************=
******=0A=
Class MoveGenerator=0A=
=0A=
MoveGenerator instproc init {} {=0A=
  [self] instvar strategy=0A=
# Dies sind die Strategie-Pattern, die unmittelbar im n=E4chsten Zug zu =
einem Sieg f=FChren=0A=
  set strategy(1,pattern) 1..1.....=0A=
  set strategy(1,move) 6=0A=
  set strategy(2,pattern) 1.....1..=0A=
  set strategy(2,move) 3=0A=
  set strategy(3,pattern) ...1..1..=0A=
  set strategy(3,move) 0=0A=
  set strategy(4,pattern) .1..1....=0A=
  set strategy(4,move) 7=0A=
  set strategy(5,pattern) .1.....1.=0A=
  set strategy(5,move) 4=0A=
  set strategy(6,pattern) ....1..1.=0A=
  set strategy(6,move) 1=0A=
  set strategy(7,pattern) ..1..1...=0A=
  set strategy(7,move) 8=0A=
  set strategy(8,pattern) ..1.....1=0A=
  set strategy(8,move) 5=0A=
  set strategy(9,pattern) .....1..1=0A=
  set strategy(9,move) 2=0A=
  set strategy(10,pattern) 11.......=0A=
  set strategy(10,move) 2=0A=
  set strategy(11,pattern) 1.1......=0A=
  set strategy(11,move) 1=0A=
  set strategy(12,pattern) .11......=0A=
  set strategy(12,move) 0=0A=
  set strategy(13,pattern) ...11....=0A=
  set strategy(13,move) 5=0A=
  set strategy(14,pattern) ...1.1...=0A=
  set strategy(14,move) 4=0A=
  set strategy(15,pattern) ....11...=0A=
  set strategy(15,move) 3=0A=
  set strategy(16,pattern) ......11.=0A=
  set strategy(16,move) 8=0A=
  set strategy(17,pattern) ......1.1=0A=
  set strategy(17,move) 7=0A=
  set strategy(18,pattern) .......11=0A=
  set strategy(18,move) 6=0A=
  set strategy(19,pattern) 1...1....=0A=
  set strategy(19,move) 8=0A=
  set strategy(20,pattern) 1.......1=0A=
  set strategy(20,move) 4=0A=
  set strategy(21,pattern) ....1...1=0A=
  set strategy(21,move) 0=0A=
  set strategy(22,pattern) ..1.1....=0A=
  set strategy(22,move) 6=0A=
  set strategy(23,pattern) ..1...1..=0A=
  set strategy(23,move) 4=0A=
  set strategy(24,pattern) ....1.1..=0A=
  set strategy(24,move) 2=0A=
}=0A=
=0A=
MoveGenerator instproc getNextMove {whoseMove} {=0A=
  [self] instvar strategy=0A=
  set pattern [board pattern]=0A=
  set movesLeft [board numFreeSquares]=0A=
  if {$movesLeft =3D=3D 0} {=0A=
    return -1=0A=
  }=0A=
# Hier wird zun=E4chst =FCberpr=FCft, ob der Computer mit dem n=E4chsten =
Zug gewinnen kann. Ist dies der Fall, macht er den entsprechenden Zug. =
Ansonsten wird =FCberpr=FCft, ob ein Sieg des Gegenspielers verhindert =
werden kann.=0A=
  for {set i 1} {$i < 25} {incr i} {=0A=
    regsub -all 1 $strategy($i,pattern) O player=0A=
    if [regexp $player $pattern] {=0A=
      if [board isVacant $strategy($i,move)] {=0A=
	return $strategy($i,move)=0A=
      }=0A=
    }=0A=
    regsub -all 1 $strategy($i,pattern) X player=0A=
    if [regexp $player $pattern] {=0A=
      if [board isVacant $strategy($i,move)] {=0A=
	return $strategy($i,move)=0A=
      }=0A=
    }=0A=
  }=0A=
# liegt kein in der Strtegie hinterlegtes Muster vor, wird als Zug die =
Mitte gew=E4hlt, falls sie frei ist=0A=
  if [board isVacant 4] {=0A=
    return 4=0A=
  }=0A=
# Ist die Mitte nicht mehr frei, wird versucht eine der Ecken zu besetzen=0A=
  set numFreeCorners [board numFreeSquares {0 2 6 8}]=0A=
  if {$numFreeCorners > 0} {=0A=
    set freeElements [board freeSquares {0 2 6 8}]=0A=
    set randomIndex [random $numFreeCorners]=0A=
# ist auch dies erfolglos, sind die vier Kantenfelder an der Reihe=0A=
  } else {=0A=
    set numFreeEdges [board numFreeSquares {1 3 5 7}]=0A=
    set freeElements [board freeSquares {1 3 5 7}]=0A=
    set randomIndex [random $numFreeEdges]=0A=
  }=0A=
  return [lindex $freeElements $randomIndex]=0A=
}=0A=
#************************************************************************=
******=0A=
# Engine Class=0A=
#************************************************************************=
******=0A=
Class Engine=0A=
=0A=
Engine instproc init {} {=0A=
  [self] instvar gameOver whoseMove messages=0A=
  set messages(NEWGAMEMSG) "New Game. Choose an X square"=0A=
  set messages(ILLEGALMOVEMSG) "Illegal Move, choose another X square"=0A=
  set messages(USERSMOVEMSG) "Choose an X square"=0A=
  set messages(WINSMSG-X) "X Wins!"=0A=
  set messages(WINSMSG-O) "O Wins!"=0A=
  set messages(TIEGAMEMSG) "Tie Game"=0A=
  set messages(GAMEISOVERMSG) "Sorry, game is over"=0A=
  set gameOver 0=0A=
  set whoseMove X=0A=
  Board board=0A=
  MoveGenerator moveGenerator=0A=
}=0A=
=0A=
Engine instproc reset {} {=0A=
  [self] instvar gameOver whoseMove messages=0A=
  set whoseMove X=0A=
  set gameOver 0=0A=
  board clear=0A=
  gameBoard clear=0A=
  msgArea postMessage $messages(NEWGAMEMSG)=0A=
}=0A=
=0A=
Engine instproc recordMove {position} {=0A=
  [self] instvar gameOver whoseMove messages =0A=
  if $gameOver {=0A=
    msgArea postAlert $messages(GAMEISOVERMSG)=0A=
    return=0A=
  }=0A=
  if [string match [board recordMove $position $whoseMove] VALIDMOVE] {=0A=
    gameBoard markSquare $position $whoseMove=0A=
  } else {=0A=
    msgArea postAlert $messages(ILLEGALMOVEMSG)=0A=
    return=0A=
  }=0A=
=0A=
  [self] checkForWin=0A=
  if $gameOver {=0A=
    return=0A=
  }=0A=
  =0A=
  if [string match $whoseMove O] {=0A=
    set whoseMove X=0A=
    msgArea postMessage $messages(USERSMOVEMSG)=0A=
  } else {=0A=
    set whoseMove O=0A=
    [self] recordMove [moveGenerator getNextMove $whoseMove]=0A=
  }=0A=
}=0A=
  =0A=
Engine instproc checkForWin {} {=0A=
  [self] instvar gameOver whoseMove messages=0A=
  set winner [board whoHasWon]=0A=
  if [string match $winner N] {=0A=
    return=0A=
  } =0A=
  set gameOver 1=0A=
  if [string match $winner TIE] {=0A=
    set winningSquares {0 0 0 0 0 0 0 0 0}=0A=
    msgArea postAlert $messages(TIEGAMEMSG)=0A=
  } else {=0A=
    set winningSquares [board winningSquares]=0A=
    msgArea postAlert $messages(WINSMSG-$winner)=0A=
  }=0A=
  for {set i 0} {$i < 9} {incr i} {=0A=
    gameBoard deactivateSquare $i=0A=
    if [lindex $winningSquares $i] {=0A=
      gameBoard highlightSquare $i=0A=
    } else {=0A=
      gameBoard deemphasizeSquare $i=0A=
    }=0A=
  }=0A=
}=0A=
=0A=
Engine instproc quit {} {=0A=
  exit=0A=
}=0A=
=0A=
#************************************************************************=
******=0A=
# Main=0A=
#************************************************************************=
******=0A=
=0A=
# XmInstallImage .top {=0A=
# /* XPM */=0A=
# static char * o_xpm[] =3D {=0A=
# "32 32 3 1",=0A=
# " 	c None s None",=0A=
# ".	c black",=0A=
# "X	c white",=0A=
# "                                ",=0A=
# "              .....             ",=0A=
# "          ....XXXXX....         ",=0A=
# "         .XXXXXXXXXXXXX.        ",=0A=
# "       ..XXXXXXXXXXXXXXX..      ",=0A=
#                : : :       =0A=
# "       ..XXXXXXXXXXXXXXX..      ",=0A=
# "         .XXXXXXXXXXXXX.        ",=0A=
# "          ....XXXXX....         ",=0A=
# "              .....             "};=0A=
# } O=0A=
# =0A=
# XmInstallImage .top {=0A=
# /* XPM */=0A=
# static char * x_xpm[] =3D {=0A=
# "32 32 2 1",=0A=
# " 	c black",=0A=
# ".	c None s None",=0A=
# "  ............................  ",=0A=
# "   ..........................   ",=0A=
# ".   ........................   .",=0A=
# "..   ......................   ..",=0A=
# "...   ....................   ...",=0A=
#               :  :  : =0A=
# "...   ....................   ...",=0A=
# "..   ......................   ..",=0A=
# ".   ........................   .",=0A=
# "   ..........................   ",=0A=
# "  ............................  "};=0A=
# } X=0A=
# =0A=
#     # Stolen from tk8.3.2\tests\imgBmap.test. =0A=
#     image create bitmap i1 -data $data1=0A=
#     i1 configure -data {=0A=
# 	#define foo2_height 14=0A=
# 	#define foo2_width 15=0A=
# 	static char foo2_bits[] =3D {=0A=
# 	   0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,=0A=
# 	   0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,=0A=
# 	   0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,=0A=
# 	   0xff, 0xff};=0A=
#     }=0A=
=0A=
image create bitmap O -foreground green -data {=0A=
  #define oooo_height 32=0A=
  #define oooo_width 32=0A=
  static char oooo_bits[] =3D {=0A=
  0x00,0x00,0x00,0x00,=0A=
  0x00,0x00,0x00,0x00,=0A=
  0x00,0xc0,0x07,0x00,=0A=
  0x00,0xfc,0x7f,0x00,=0A=
  0x00,0xfe,0xff,0x00,=0A=
  0x80,0xff,0xff,0x03,=0A=
  0xc0,0xff,0xff,0x07,=0A=
  0xe0,0xff,0xff,0x0f,=0A=
  0xe0,0xff,0xff,0x0f,=0A=
  0xf0,0xff,0xff,0x1f,=0A=
  0xf8,0xff,0xff,0x3f,=0A=
  0xf8,0xff,0xff,0x3f,=0A=
  0xf8,0xff,0xff,0x3f,=0A=
  0xf8,0xff,0xff,0x3f,=0A=
  0xfc,0xff,0xff,0x7f,=0A=
  0xfc,0xff,0xff,0x7f,=0A=
  0xfc,0xff,0xff,0x7f,=0A=
  0xfc,0xff,0xff,0x7f,=0A=
  0xfc,0xff,0xff,0x7f,=0A=
  0xf8,0xff,0xff,0x3f,=0A=
  0xf8,0xff,0xff,0x3f,=0A=
  0xf8,0xff,0xff,0x3f,=0A=
  0xf8,0xff,0xff,0x3f,=0A=
  0xf0,0xff,0xff,0x1f,=0A=
  0xe0,0xff,0xff,0x0f,=0A=
  0xe0,0xff,0xff,0x0f,=0A=
  0xc0,0xff,0xff,0x07,=0A=
  0x80,0xff,0xff,0x03,=0A=
  0x00,0xfe,0xff,0x00,=0A=
  0x00,0xfc,0x7f,0x00,=0A=
  0x00,0xc0,0x07,0x00,=0A=
  0x00,0x00,0x00,0x00};=0A=
}=0A=
# Image create bitmap name -data {...} returns the name as its return =
value. =0A=
=0A=
image create bitmap X -foreground green -data {=0A=
  #define xxxx_height 32=0A=
  #define xxxx_width 32=0A=
  static char xxxx_bits[] =3D {=0A=
  0xfc,0xff,0xff,0x3f,=0A=
  0xf8,0xff,0xff,0x1f,=0A=
  0xf1,0xff,0xff,0x8f,=0A=
  0xe3,0xff,0xff,0xc7,=0A=
=0A=
  0xc7,0xff,0xff,0xe3,=0A=
  0x8f,0xff,0xff,0xf1,=0A=
  0x1f,0xff,0xff,0xf8,=0A=
  0x3f,0xfe,0x7f,0xfc,=0A=
=0A=
  0x7f,0xfc,0x3f,0xfe,=0A=
  0xff,0xf8,0x1f,0xff,=0A=
  0xff,0xf1,0x8f,0xff,=0A=
  0xff,0xe3,0xc7,0xff,=0A=
=0A=
  0xff,0xc7,0xe3,0xff,=0A=
  0xff,0x8f,0xf1,0xff,=0A=
  0xff,0x1f,0xf8,0xff,=0A=
  0xff,0x3f,0xfc,0xff,=0A=
=0A=
  0xff,0x3f,0xfc,0xff,=0A=
  0xff,0x1f,0xf8,0xff,=0A=
  0xff,0x8f,0xf1,0xff,=0A=
  0xff,0xc7,0xe3,0xff,=0A=
=0A=
  0xff,0xe3,0xc7,0xff,=0A=
  0xff,0xf1,0x8f,0xff,=0A=
  0xff,0xf8,0x1f,0xff,=0A=
  0x7f,0xfc,0x3f,0xfe,=0A=
=0A=
  0x3f,0xfe,0x7f,0xfc,=0A=
  0x1f,0xff,0xff,0xf8,=0A=
  0x8f,0xff,0xff,0xf1,=0A=
  0xc7,0xff,0xff,0xe3,=0A=
=0A=
  0xe3,0xff,0xff,0xc7,=0A=
  0xf1,0xff,0xff,0x8f,=0A=
  0xf8,0xff,0xff,0x1f,=0A=
  0xfc,0xff,0xff,0x3f};=0A=
}=0A=
# The upper-right to lower-left stripe is narrower than the upper-left =0A=
# to lower-right stripe.  I have no idea why. =0A=
=0A=
# I've decided to have an explicit nothingness bitmap.  When there is =
*no* =0A=
# bitmap, Tk interprets the height and width in terms of characters. =0A=
image create bitmap N -data {=0A=
  #define nnnn_height 32=0A=
  #define nnnn_width 32=0A=
  static char nnnn_bits[] =3D {=0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00, =0A=
  0x00, 0x00, 0x00, 0x00};=0A=
}=0A=
=0A=
TicTacToe game .top=0A=
# realize=0A=
=0A=
# XmXxxx things we'll have to replace: =0A=
# =0A=
# XmPushButton=0A=
# XmForm=0A=
# XmSeparator=0A=
# XmRowColumn=0A=
# XmDrawnButton=0A=
# XmLabel=0A=
# XmInstallImage=0A=

------=_NextPart_000_0000_01C0AB13.AFA0C050--