%%% %%% Authors: %%% Christian Schulte %%% %%% Copyright: %%% Christian Schulte, 1997 %%% %%% Last change: %%% $Date: 1999-05-27 18:51:46 +0200 (Thu, 27 May 1999) $ by $Author: schulte $ %%% $Revision: 11391 $ %%% %%% This file is part of Mozart, an implementation %%% of Oz 3 %%% http://www.mozart-oz.org %%% %%% See the file "LICENSE" or %%% http://www.mozart-oz.org/LICENSE.html %%% for information on usage and redistribution %%% of this file, and for a DISCLAIMER OF ALL %%% WARRANTIES. %%% functor require DemoUrls(image) import FD Space Tk TkTools Application prepare URL = {VirtualString.toAtom DemoUrls.image # 'animated-queens/'} MaxWidth = 600 % How large can the drawing area be FailWidth = 10 DefaultSize = 6 % With which N-Queens problem should we start ParamWinTitle = 'Animated Queens: Size' %% Derived Parameters WidthByMag = s(micro:2 tiny:5 small:10 middle:25 large:50) MaxBoardSize = 255 define LargeFont = {New Tk.font tkInit(family:times weight:bold size:~24)} BlackColor # WhiteColor # QueenColor # CrossColor # FailColor = if Tk.isColor then gray85 # gray95 # darkorange1 # gray75 # firebrick else black # white # black # black # black end QueenByMag = {List.toRecord '' {Map [micro tiny small middle large] fun {$ S} S#{New Tk.image tkInit(type:bitmap foreground:QueenColor url: URL # S# '-queen.xbm')} end}} CrossByMag = c(micro: false tiny: false small: false middle: {New Tk.image tkInit(type:bitmap foreground:CrossColor url: URL # 'middle-cross.xbm')} large: {New Tk.image tkInit(type:bitmap foreground:CrossColor url: URL # 'large-cross.xbm')}) NaiveStrat = 1 FirstFailStrat = 2 UpFirstStrat = 3 MiddleOutStrat = 4 DefaultStrat = MiddleOutStrat %% %% The problem solving part %% local fun {OrderUp X Y} SizeX = {FD.reflect.size X} SizeY = {FD.reflect.size Y} in SizeX < SizeY orelse SizeX==SizeY andthen {FD.reflect.min X} < {FD.reflect.min Y} end fun {QueensScript Size Strategy} Distribute = case Strategy of !NaiveStrat then naive [] !FirstFailStrat then ff [] !UpFirstStrat then generic(order:OrderUp) [] !MiddleOutStrat then generic(value:mid) end in proc {$ Xs} Xs = {FD.list Size 1#Size} {FD.distinct Xs} {FD.distinctOffset Xs {List.number 1 Size 1}} {FD.distinctOffset Xs {List.number Size 1 ~1}} {FD.distribute Distribute Xs} end end in class Engine feat canvas attr Stack: nil Stopped: false meth init(Size Strategy Canvas) S={Space.new {QueensScript Size Strategy}} in Stopped <- false Stack <- [S] self.canvas = Canvas {self next} end meth next case @Stack of nil then {self finish} Stopped <- true {self.canvas stop} [] S|Sr then if S==backtrack then Stack <- Sr {self backtrack} Engine,next else {self show(S)} case {Space.ask S} of alternatives(M) then C={Space.clone S} in {Space.commit S 1} {Space.commit C 2#M} Stack <- S|C|backtrack|Sr [] failed then Stack <- backtrack|Sr [] succeeded then Stack <- backtrack|Sr Stopped <- true {self.canvas stop} end end end end meth sol Engine, next if @Stopped then skip else Engine,sol end end meth stop Stopped <- true end meth start Stopped <- false end end end local fun {ReflectForCrosses Xs} case Xs of nil then nil [] X|Xr then {FD.reflect.domList X}|{ReflectForCrosses Xr} end end fun {Reflect Xs} case Xs of nil then nil [] X|Xr then if {FD.reflect.size X}==1 then X else void end|{Reflect Xr} end end in fun {MakePainter Canvas Mag Size} Width = WidthByMag.Mag Cross = CrossByMag.Mag Queen = QueenByMag.Mag Total = Size * Width Fail0 = Total div 4 Fail1 = Fail0 + Total div 2 proc {DrawFail T} {Canvas tk(create line Fail0 Fail0 Fail1 Fail1 width:FailWidth fill:FailColor capstyle:round tags:T)} {Canvas tk(create line Fail0 Fail1 Fail1 Fail0 width:FailWidth fill:FailColor capstyle:round tags:T)} end proc {DrawQueen X Y T} if X\=void andthen Y\=void then {Canvas tk(create image (X-1)*Width (Y-1)*Width image: Queen tags: T anchor: nw)} end end UpdateBoard ReflectBoard if Cross\=false then proc {DrawCross X Y T} {Canvas tk(create image (X-1)*Width (Y-1)*Width image: Cross tags: T anchor: nw)} end proc {DrawCrosses Os Ns I T} case Os of nil then skip [] O|Or then case Ns of nil then {DrawCross O I T} {DrawCrosses Or Ns I T} [] N|Nr then {DrawCrosses Or if O