Module: reversi Author: Andy Armstrong Synopsis: Reversi game Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND //---------------------------------------------------------------------------- // Reversi square // // This is a sheet that draws itself as a square with an optional // coloured piece upon it. //---------------------------------------------------------------------------- define variable *reversi-square-color* = $red; define variable *reversi-square-size* = 30; define variable *reversi-piece-shape* = #"circle"; define class () slot square-number = #f, init-keyword: number:; slot %piece = #f, init-keyword: piece:; end class ; define method square-piece (sheet :: ) => (piece :: ) sheet.%piece end method square-piece; define method square-piece-setter (piece :: , sheet :: ) => (piece :: ) sheet.%piece := piece; if (sheet-mapped?(sheet)) repaint-sheet(sheet, $everywhere) end; piece; end method square-piece-setter; define method do-compose-space (sheet :: , #key width, height) => (space-requirement :: ) make(, width: *reversi-square-size*, height: *reversi-square-size*); end method do-compose-space; define method handle-repaint (sheet :: , medium :: , region :: ) => () let (left, top, right, bottom) = box-edges(sheet); let frame = sheet-frame(sheet); with-drawing-options (medium, brush: default-background(sheet)) draw-rectangle(medium, left, top, right, bottom, filled?: #t) end; draw-piece(sheet, medium, *reversi-piece-shape*) end method handle-repaint; define method handle-event (square :: , event :: ) => () let frame = sheet-frame(square); if (frame) if (event-button(event) = $left-button) reversi-frame-press-square(frame, square-number(square)); force-display(port(square)) end; end; end method handle-event; define method draw-piece (sheet :: , medium :: , shape == #"circle") => () when (square-piece(sheet)) let (left, top, right, bottom) = box-edges(sheet); let half-width = floor/(right - left, 2); let half-height = floor/(bottom - top, 2); let x-radius = floor/(right - left, 3); let y-radius = floor/(bottom - top, 3); let color = select (square-piece(sheet)) #"black" => $black; #"white" => $white; end; with-drawing-options (medium, brush: color) draw-ellipse(medium, left + half-width, top + half-height, x-radius, 0, 0, y-radius, filled?: #t); end; end; end method draw-piece; //---------------------------------------------------------------------------- // Reversi frame // // This really is just a presentation of the abstract game defined by // the class . //---------------------------------------------------------------------------- //--- We need to pick up something pretty as the frame background //--- (in CLOS, we'd use :default-init-keywords (:background ...)) define frame () slot reversi-square-color = *reversi-square-color*, init-keyword: square-color:; slot %game :: false-or() = #f; slot %squares :: false-or() = #f; slot %saved-file-name :: false-or() = #f; pane buttons (frame) make(, label: "New game", activate-callback: reversi-frame-new-game); pane size-box (frame) begin let game = reversi-frame-game(frame); make(, items: #(6, 8, 10, 12, 14, 16, 18, 20, 22, 24), value: reversi-game-size(game), value-changed-callback: method (b) reversi-frame-change-size(sheet-frame(b), gadget-value(b)) end, label-key: method (item) format-to-string("%d", item) end) end; pane reversi-frame-table-pane (frame) begin let game = reversi-frame-game(frame); make(, children: reversi-frame-squares(frame), cell-space-requirement: make(, width: *reversi-square-size*, height: *reversi-square-size*), rows: reversi-game-size(game), spacing: 2) end; pane status (frame) make(); pane main-layout (frame) vertically (spacing: 2) horizontally (spacing: 2, y-alignment: #"center") frame.buttons; /** Removed for the demo since spin boxes aren't implemented natively! make(