Computer Graphics Workshop '96 Lecture Notes

2/2/96

Today's topics
Final projects

The following projects were done by students taking this course over IAP 1996 at MIT, from January 8 to February 2.

Battleship - Debajit Ghosh

"Battleship" is a work in progress -- it implements the interface to the game Battleship, but not the game engine itself. It demonstrates a client-server program in Scheme using Inventor.

Download the source code

bship.scm

;; bship.scm
;; Debajit Ghosh
;; 1/30/96

(define my-view (new-SoXtExaminerViewer))  ; viewer for your own board
                                           ; in this version, everything
                                           ; happens here
(define opp-view (new-SoXtExaminerViewer)) ; not used yet

(define root (new-SoSelection))

(-> my-view 'setSceneGraph root)
(-> my-view 'setTitle "Your Board")
(-> my-view 'setViewing 0)
(-> my-view 'show)


;; generate coordinates for an dim x dim board

(define (gen-coords x y dim)
  (if (< x dim)
      (if (< y dim)
	  (cons
	   (list (+ 0.5 x) (+ 0.5 y) 0 (string-append "_"
						      (number->string
						       (+ (* x dim) y))))
	   (gen-coords x (+ y 1) dim))
	  (gen-coords (+ x 1) 0 dim))
      '()))

;;; SICP-ish simple object system for dealing similarly
     ;;; with Scheme and C++ objects using "send"

(define (send object message . args)
  (if (C++-object? object)
      (eval `(-> ,object ',message ,@args))
      (let ((method (get-method object message)))
	(if (not (no-method? method))
	    (apply method (cons object args))
	    (error "No method named" message)))))

(define (get-method object message)
  (object message))

(define (no-method method)
  'no-method)

(define (no-method? method)
  (eq? method 'no-method))


;; constructor for the board object

(define (new-Board dim)
  (define root (new-SoSeparator))
  (send root 'ref)
  (define coordinates (gen-coords 0 0 dim))

  (lambda (message)
         ;;; Method to return pointer to root of scene graph
    (cond ((eq? message 'getGeometry)
	   (lambda (self)
	     root))
	  ;;; get the coordinates of nodes on this board
	  ((eq? message 'getCoords)
	   (lambda (self)
	     coordinates))
	  ;;; generate the board
	  ((eq? message 'generate)
	   (lambda (self)
	     (let loop
		 ((coords coordinates))
	       (if (not (null? coords))
		   (let ((transvalue (car coords)))
		     (begin
		       (display transvalue)
		       (define s (new-SoSeparator))
		       (send root 'addChild s)
		       (define t (new-SoTransform))
		       (send s 'addChild t)
		       (send (send t 'translation) 'setValue (car transvalue)
			     (cadr transvalue) (caddr transvalue))
		       (define m (new-SoMaterial))
		       (send s 'addChild m)
		       (define node (new-SoSphere))
		       (send (send node 'radius) 'setValue 0.1)
		       (send node 'setname (new-sbname (cadddr transvalue)))
		       (send s 'addChild node)
		       (loop (cdr coords))))))))
	  ;;; turn a node that has been "hit" blue
	  ((eq? message 'hitNode)
	   (lambda (self index)
	     (let* ((sel (SoSeparator-cast (send root 'getChild index)))
		    (mat (SoMaterial-cast (send sel 'getChild 1))))
	       (send (send mat 'diffuseColor) 'setValue 0.0 0.0 1.0))))
	       
	  (else (no-method message)))))

;; set up everything

(define board (new-Board 3))
(send root 'addChild (send board 'getGeometry))
(send board 'generate)


;; set up selection callback
(define callback-info (new-SchemeSoCBInfo))
(-> callback-info 'ref)
(-> (-> callback-info 'callbackName) 'setValue "selection-callback")
(-> root 'addSelectionCallback (get-scheme-selection-path-cb) 
    (void-cast callback-info))

(define (selection-callback data path)
       (let* ((selected-object (-> path 'getTail))
	      (sel-obj-pop (-> path 'pop))
	      (sel-obj-par (SoSeparator-cast (-> path 'getTail))))
         (if (= 1 (-> selected-object 'isOfType (SoSphere::getClassTypeId)))
             (let* ((the-sphere (SoSphere-cast selected-object))
		    (sphere-name (-> the-sphere 'getName))
		    (sphere-string (-> sphere-name 'getString))
		    (sphere-mat (SoMaterial-cast (-> sel-obj-par 'getChild 1))))
	       (display sphere-string)
	       (-> (-> sphere-mat 'diffuseColor) 'setValue 1.0 0.0 0.0)
               (newline)
	       (send-over-network sphere-string)))))

;;; idle callback, basically check to see if any "hits" have been made
;;; during idle cycles

(define idle-cb
  (lambda (user-data sensor)
    ;; Tell sensor to reschedule
    (begin
      (send sensor 'schedule)
      (let ((index-string (get-from-network)))
	(if (not (null? index-string))
	    (send board 'hitNode (string->number 
				  (substring index-string
					     1
					     (string-length index-string)))))))))

;; Callback information node for the idle sensor's callback
(define cb-info (new-SchemeSoCBInfo))
(-> cb-info 'ref)
(-> (-> cb-info 'callbackName) 'setValue "idle-cb")

;; Creation and scheduling of the idle sensor
(define idle-sensor (new-SoIdleSensor (get-scheme-sensor-cb) 
				      (void-cast cb-info)))
(-> idle-sensor 'schedule)
bship-server.scm
;; bship-server.scm
;; the battleship server

(load "bship")
(define *bship-port* 8001)

;; create the server
(define server (new-SocketMan *bship-port*))


;; wait for connection from client loop
(define (accept-connection-loop)
  (if (not (= SocketMan::MSG_NO_ERROR
	      (send server 'acceptConnectionWithPoll)))
      (accept-connection-loop)))

(display "Waiting for client connection...hit CTRL-C to abort.\n")
;; start waiting..
(accept-connection-loop)

;; methods for network activity for server..

(send server 'rewindSockets)
(if (= 0 (send server 'nextSocket))
    (error "WHOA! Client disappeared!" server))

(define (send-over-network object)
  (write-object-to-network object server))

(define (get-from-network)
  (read-object-from-network server))
bship-client.scm
;; bship-client.scm
;;; battleship client -- more SocketMan magic

(load "bship")
(define *bship-port* 8001)


;;; create the client
(define client (new-SocketClient *bship-port*))

;;; get the server name
(define (read-loop)
  (display "Enter the server name IN DOUBLE QUOTES: ")
  (let ((response (read)))
    (if (not (string? response))
	(begin
	  (display "Please enter the name of the server IN DOUBLE QUOTES.\n")
	  (read-loop))
	response)))

;;; loop used for trying to connect to a server
(define (connect-to-server-loop)
  (let ((the-response (send client 'connectToServer server-name)))
    (if (not (= SocketMan::MSG_NO_ERROR the-response))
	(begin
	  (socketman-print-error the-response)
	  (if (= SocketMan::ERR_UNKNOWN_HOST the-response)
	      (set! server-name (read-loop)))
	  (connect-to-server-loop)))))

(define server-name (read-loop))

(display "Connecting to server...hit CTRL-C to abort.\n")


;;; wait until connection is established
(connect-to-server-loop)


;;; methods for network activity for client
(define (send-over-network object)
  (write-object-to-network object client))

(define (get-from-network)
  (read-object-from-network client))
Inventor-Man! - Janet Marques

Inventor Man is a 3D version of Pac-Man, programmed in SCHEME using Open Inventor. The object is to paint all of the pellets before the evil spheres catch you. Use the 4 warps to escape a close call.

Download the source code

inventor-man.scm

;; Inventor-Man
;; Copyright 1996, Janet Marques. 

(define pi 3.1415926585)
(define counter 0)
(define winlist '())

(define (send object message . args)
  (if (C++-object? object)
      (eval `(-> ,object ',message ,@args))
      (let ((method (get-method object message)))
	(if (not (no-method? method))
	    (apply method (cons object args))
	    (error "No method named" message)))))

(define (get-method object message)
  (object message))

(define (no-method method)
  'no-method)

(define (no-method? method)
  (eq? method 'no-method))

;(define (make-object)
;  (lambda (message)
;    (cond ((eq? message 'hi)
;	   (lambda (self arg1 arg2)
;	     (format #t "arg1: ~a arg2: ~a~%" arg1 arg2)))
;	  (else (no-method message)))))

(define root (new-SoSeparator))
(-> root 'ref)
(define event-callback (new-SoEventCallback))
(-> root 'addchild event-callback)
(define Viewer (new-SoXtExaminerViewer))
(-> Viewer 'SetSceneGraph root)
(-> viewer 'setViewing 0)
(define root-trans (new-SoTransform))
(-> root 'addchild root-trans)
(-> (-> root-trans 'rotation) 'setvalue 1 -.3 0 -4.5)
(-> Viewer 'show)
(define pellet-node (new-SoSeparator))
(-> root 'addchild pellet-node)
(define scale (new-SoScale))
(-> pellet-node 'addchild scale)
(-> (-> scale 'scalefactor) 'SetValue .01 .01 .01)

(define right-list (list '(-0.1 -0.7 0.0) '(0.7 -0.7 0.0) 
			 '(-0.7 -0.6 0.0) '(-0.4 -0.6 0.0) 
			 '(0.1 -0.6 0.0) '(0.4 -0.6 0.0) 
			 '(0.7 -0.6 0.0) '(-0.7 -0.5 0.0) 
			 '(-0.1 -0.5 0.0) '(0.5 -0.5 0.0) 
			 '(0.7 -0.5 0.0) '(-0.7 -0.4 0.0) 
			 '(-0.5 -0.4 0.0) '(-0.2 -0.4 0.0) 
			 '(0.5 -0.4 0.0) '(0.2 -0.1 0.0) 
			 '(0.2 0.0 0.0)  '(0.5 0.4 0.0) 
			 '(0.2 0.1 0.0) '(0.7 0.3 0.0) 
			 '(0.7 -0.3 0.0) '(0.0 0.2 0.0) 
			 '(-0.7 -0.2 0.0) '(-0.4 -0.2 0.0) 
			 '(-0.7 0.2 0.0) '(-0.7 -0.2 0.0)
			 '(-0.7 0.4 0.0) '(-0.7 -0.4 0.0)
			 '(0.4 -0.2 0.0) '(0.7 -0.2 0.0)
			 '(-0.4 -0.1 0.0) '(0.7 -0.1 0.0)
			 '(-0.4  0.0 0.0) '(0.4 0.0 0.0)
			 '(-0.1 0.7 0.0) '(0.7 0.7 0.0)
			 '(-0.7 0.6 0.0) '(-0.4 0.6 0.0)
			 '(0.1 0.6 0.0) '(0.4 0.6 0.0)
			 '(0.7 0.6 0.0) '(-0.7 0.5 0.0)
			 '(-0.1 0.5 0.0) '(0.5 0.5 0.0)
			 '(0.7 0.5 0.0) '(-0.7 0.4 0.0)
			 '(-0.5 0.4 0.0) '(-0.2 0.4 0.0)
			 '(-0.7 0.2 0.0) '(-0.4 0.2 0.0)
			 '(-0.7 0.2 0.0) '(-.7 0.4 0.0)
			 '(0.4 0.2 0.0) '(0.7 0.2 0.0)
			 '(-0.4 0.1 0.0) '(0.7 0.1 0.0)
			 '(0.2 0.4 0.0) '(0.2 -0.4 0.0)
			 '() ))

(define left-list (list  '(-0.7 -0.3 0.0) '(-0.7 -0.6 0.0)
			 '(-0.7 -0.5 0.0) '(-0.7 0.5 0.0) 
			 '(-0.7 -0.7 0.0) '(-0.7 -0.2 0.0)
			 '(-0.7 -0.1 0.0) '(-0.7 0.1 0.0)
			 '(-0.7 0.2 0.0) '(-0.7 0.3 0.0)
			 '(-0.7 0.6 0.0) '(-0.7 0.7 0.0)
			 '(-0.5 -0.5 0.0) '(-0.5 -0.4 0.0)
			 '(-0.5 0.5 0.0) '(-0.5 0.4 0.0)
			 '(-0.4 -0.6 0.0) '(-0.4 -0.2 0.0)
			 '(-0.4 -0.0 0.0) '(-0.4 0.2 0.0)
			 '(-0.4 0.6 0.0) '(-0.2 -0.4 0.0)
			 '(-0.2 0.4 0.0) '(-0.1 -0.6 0.0)
			 '(-0.1 0.6 0.0) '(0.1 0.7 0.0)
			 '(0.7 -0.6 0.0) '(-0.2 0.1 0.0)
			 '(0.7 -0.5 0.0) '(0.7 -0.4 0.0)
			 '(0.7 -0.2 0.0) '(-0.2 0.0 0.0)
			 '(-0.2 -0.1 0.0) '(0.0 0.2 0.0)
			 '(0.7 0.2 0.0) '(0.7  0.6 0.0) 
			 '(0.7 0.5 0.0) '(0.7 0.4 0.0)
			 '(0.5 -0.4 0.0) '(0.5  0.4 0.0)
			 '(0.4 -0.1 0.0) '(0.4 0.1 0.0)
			 '(0.4 -0.6 0.0) '(0.4 -0.2 0.0)
			 '(0.4 -0.0 0.0) '(0.4 0.2 0.0)
			 '(0.4 0.6 0.0) '(0.2 -0.4 0.0)
			 '(0.2 0.4 0.0) '(0.1 -0.7 0.0)
			 '(0.1 0.5 0.0) '(0.1 -0.5 0.0)
			 '(0.1 -0.7 0.0) '() ))

(define north-list (list  '(-0.7 -0.1 0.0) '(-0.7 0.7 0.0)
			  '(-0.6 -0.7 0.0) '(-0.6 -0.3 0.0)
			  '(-0.6 -0.1 0.0) '(-0.6 0.1 0.0)
			  '(-0.6 0.3 0.0) '(-0.6 0.7 0.0)
			  '(-0.5 -0.7 0.0) '(-0.5 -0.3 0.0)
			  '(-0.5 -0.1 0.0) '(-0.5 0.1 0.0)
			  '(-0.5 0.5 0.0) '(-0.5 0.7 0.0)
			  '(-0.4 -0.5 0.0) '(-0.4 0.3 0.0)
			  '(-0.4 0.7 0.0) '(-0.3 -0.7 0.0)
			  '(-0.3 -0.5 0.0) '(-0.3 -0.3 0.0)
			  '(-0.3 0.3 0.0) '(-0.3 0.5 0.0)
			  '(-0.3 0.7 0.0) '(-0.2 -0.7 0.0)
			  '(-0.2 -0.3 0.0) '(-0.2 0.1 0.0)
			  '(-0.2 0.5 0.0) '(-0.2 0.7 0.0)
			  '(-0.1 -0.5 0.0) '(-0.1 -0.3 0.0)
			  '(-0.1 0.1 0.0) '(-0.1 0.3 0.0)
			  '(-0.1 0.7 0.0) '(0.1 0.7 0.0)
			  '(0.7 -0.1 0.0) '(0.7 0.7 0.0)
			  '(0.6 -0.7 0.0) '(0.6 -0.3 0.0)
			  '(0.6 -0.1 0.0) '(0.6 0.1 0.0)
			  '(0.6 0.3 0.0) '(0.6 0.7 0.0)
			  '(0.5 -0.7 0.0) '(0.5 -0.3 0.0)
			  '(0.5 -0.1 0.0) '(0.5 0.1 0.0)
			  '(0.5 0.5 0.0) '(0.5 0.7 0.0)
			  '(0.4 -0.5 0.0) '(0.4 0.3 0.0)
			  '(0.4 0.7 0.0) '(0.3 -0.7 0.0)
			  '(0.3 -0.5 0.0) '(0.3 -0.3 0.0)
			  '(0.3 0.3 0.0) '(0.3 0.5 0.0)
			  '(0.3 0.7 0.0) '(0.2 -0.7 0.0)
			  '(0.2 -0.3 0.0) '(0.2 0.1 0.0)
			  '(0.2 0.5 0.0) '(0.2 0.7 0.0)
			  '(0.1 -0.5 0.0) '(0.1 -0.3 0.0)
			  '(0.1 0.1 0.0) '(0.1 0.3 0.0)
			  '(0.0 -0.6 0.0) '(0.0 -0.3 0.0)
			  '(0.0 0.3 0.0) '(0.0 0.6 0.0)
			  '(0.0 0.6 0.0) '(0.8 0.4 0.0)
			  '(-0.8 0.4 0.0) '(0.8 -0.4 0.0)
			  '(-0.8 -0.4 0.0) '() ))

(define south-list  (list '(-0.7 0.1 0.0) '(-0.7 -0.7 0.0)
			  '(-0.6 0.7 0.0) '(-0.6 0.3 0.0)
			  '(-0.6 0.1 0.0) '(-0.6 -0.1 0.0)
			  '(-0.6 -0.3 0.0) '(-0.6 -0.7 0.0)
			  '(-0.5 0.7 0.0) '(-0.5 0.3 0.0)
			  '(-0.5 0.1 0.0) '(-0.5 -0.1 0.0)
			  '(-0.5 -0.5 0.0) '(-0.5 -0.7 0.0)
			  '(-0.4 0.5 0.0) '(-0.4 -0.3 0.0)
			  '(-0.4 -0.7 0.0) '(-0.3 0.7 0.0)
			  '(-0.3 0.5 0.0) '(-0.3 0.3 0.0)
			  '(-0.3 -0.3 0.0) '(-0.3 -0.5 0.0)
			  '(-0.3 -0.7 0.0) '(-0.2 0.7 0.0)
			  '(-0.2 0.3 0.0) '(-0.2 -0.1 0.0)
			  '(-0.2 -0.5 0.0) '(-0.2 -0.7 0.0)
			  '(-0.1 0.5 0.0) '(-0.1 0.3 0.0)
			  '(-0.1 -0.1 0.0) '(-0.1 -0.3 0.0)
			  '(-0.1 -0.7 0.0) '(0.1 -0.7 0.0)
			  '(0.7 0.1 0.0) '(0.7 -0.7 0.0)
			  '(0.6 0.7 0.0) '(0.6 0.3 0.0)
			  '(0.6 0.1 0.0) '(0.6 -0.1 0.0)
			  '(0.6 -0.3 0.0) '(0.6 -0.7 0.0)
			  '(0.5 0.7 0.0) '(0.5 0.3 0.0)
			  '(0.5 0.1 0.0) '(0.5 -0.1 0.0)
			  '(0.5 -0.5 0.0) '(0.5 -0.7 0.0)
			  '(0.4 0.5 0.0) '(0.4 -0.3 0.0)
			  '(0.4 -0.7 0.0) '(0.3 0.7 0.0)
			  '(0.3 0.5 0.0) '(0.3 0.3 0.0)
			  '(0.3 -0.3 0.0) '(0.3 -0.5 0.0)
			  '(0.3 -0.7 0.0) '(0.2 0.7 0.0)
			  '(0.2 0.3 0.0) '(0.2 -0.1 0.0)
			  '(0.2 -0.5 0.0) '(0.2 -0.7 0.0)
			  '(0.1 0.5 0.0) '(0.1 0.3 0.0)
			  '(0.1 -0.1 0.0) '(0.1 -0.3 0.0)
			  '(0.0 0.6 0.0) '(0.0 -0.1 0.0)
			  '(0.0 -0.3 0.0) '(0.0 -0.6 0.0)
			  '(0.0 -0.6 0.0) '(0.0 0.4 0.0)
			  '(0.8 0.4 0.0)  '(-0.8 -0.4 0.0)
			  '(-0.8 0.4 0.0) '(0.8 -0.4 0.0)
			  '(0.0 0.3 0.0) '() ))

(define (make-inven-man)
  (define inven-root (new-SoSeparator))
  (send root 'addchild inven-root)
  (define inven-trans (new-SoTransform))
  (send inven-root 'addchild inven-trans)
  (define inven-mat (new-SoMaterial))
  (send inven-root 'addchild inven-mat)
  (-> (-> inven-mat 'DiffuseColor) 'SetValue 0.0 0.0 .6)
  (define inven-man (new-SoSphere))
  (send inven-root 'addchild inven-man)
  (-> (-> inven-man 'radius) 'SetValue .05)
  (-> (-> inven-trans 'translation) 'SetValue 0.0 -0.3 0.0)
  (define callback-info (new-SchemeSoCBInfo))
  (-> callback-info 'ref)
  (-> (-> callback-info 'callbackName) 'setValue "key-event-cb")
  (-> (-> callback-info 'affectsNode) 'setValue inven-trans)
  (-> event-callback 'addEventCallback (SoKeyboardEvent::getClassTypeId)
      (get-scheme-event-callback-cb)
      (void-cast callback-info))
  (lambda (message)
    (cond ((eq? message 'SetInitial)
	   (lambda (self)
	     (-> (-> inven-trans 'translation) 'SetValue 0.0 -0.3 0.0)))
	  ((eq? message 'setcolor)
	   (lambda (self r g b)
	     (send (send inven-mat 'diffuseColor) 'SetValue r g b)))
	  ((eq? message 'setLocation)
	   (lambda (self x1 y1 z1)
	     (send (send inven-trans 'translation) 'SetValue x1 y1 z1)))
	  ((eq? message 'SetRadius)
	   (lambda (self radius)
	     (send (send inven-man 'Radius) 'SetValue radius)))
	  ((eq? message 'right)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2)))
	       (if (member (vector->list coord)
			   (list '(0.8 0.4 0.0) 
				 '(0.8 -0.4 0.0) '()))   
		   (send (send inven-trans 'translation) 
			 'setValue (- 0.0 x1) y1 z1)			
		   (if (not (member (vector->list coord) right-list))
		       (begin
			 (send (send inven-trans 'translation) 'setValue 
			       (+ x1 0.1) y1 z1)
			 (if (not (member (vector->list coord)
					  (list '(-0.8 0.4 0.0) 
						'(-0.8 -0.4 0.0) '()))) 
			     (begin
			       (put-pellet (vector (* 100 x1) (* 100 y1) 0.0) 					     0 0 .6)
			       (win? coord)))))))))
	  ((eq? message 'left)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2)))
	       (if (member (vector->list coord)
			   (list '(-0.8 0.4 0.0) '(-0.8 -0.4 0.0) '()))   
		   (send (send inven-trans 'translation) 
			 'setValue (- 0.0 x1) y1 z1)			
		   (if (not (member (vector->list coord) left-list))
		       (begin
			 (send (send inven-trans 'translation) 'setValue 
			       (- x1 0.1) y1 z1)
			 (if (not (member (vector->list coord)
					  (list '(0.8 0.4 0.0) 
						'(0.8 -0.4 0.0) '())))
			     (begin
			       (put-pellet (vector (* 100 x1) (* 100 y1) 0.0) 
					   0 0 .6)
			       (win? coord)))))))))
	  ((eq? message 'north)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2)))	              
	       (if (not (member (vector->list coord) north-list))
		   (begin
		     (send (send inven-trans 'translation) 'setValue 
			   x1 (+ y1 0.1) z1)
		     (put-pellet (vector (* 100 x1) (* 100 y1) 0.0) 
				 0 0 .6)
		     (win? coord))))))
	  ((eq? message 'south)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2)))               
	       (if (not (member (vector->list coord) south-list))
		   (begin
		       (send (send inven-trans 'translation) 'setValue 
			     x1 (- y1 0.1) z1)
		       (put-pellet (vector (* 100 x1) (* 100 y1) 0.0) 
				   0 0 .6)
		       (win? coord))))))
	  ((eq? message 'nowhere)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2)))
	       (send (send inven-trans 'translation) 'setValue x1 y1 z1))))
	  ((eq? message 'getlocation)
	   (let ((coord (-> (-> (-> inven-trans 'translation) 
				'GetValue) 'GetValue)))
	     (lambda (self)
	       (vector (/ (round (* 10 (vector-ref coord 0))) 10)
		       (/ (round (* 10 (vector-ref coord 1))) 10)
		       (/ (round (* 10 (vector-ref coord 2))) 10))))))))
  
(define (key-event-cb user-data event-node)
  (let ((event (send event-node 'getEvent)))
    (cond ((= 1 (SO_KEY_PRESS_EVENT event LEFT_ARROW))
	   (send inventor-man 'left))
	  ((= 1 (SO_KEY_PRESS_EVENT event RIGHT_ARROW))
	   (send inventor-man 'right))
	  ((= 1 (SO_KEY_PRESS_EVENT event UP_ARROW))
	   (send inventor-man 'north))
	  ((= 1 (SO_KEY_PRESS_EVENT event DOWN_ARROW))
	   (send inventor-man 'south))
	  (else (send inventor-man 'nowhere)))
    (send event-node 'setHandled)))

(define inventor-man (make-inven-man))
(load "maze.scm")

(define (make-ghost x y r g b)
  (define ghost-root (new-SoSeparator))
  (send root 'addchild ghost-root)
  (define ghost-trans (new-SoTransform))
  (send ghost-root 'addchild ghost-trans)
  (define ghost-mat (new-SoMaterial))
  (send ghost-root 'addchild ghost-mat)
  (-> (-> ghost-mat 'DiffuseColor) 'SetValue r g b)
  (define ghost (new-SoSphere))
  (send ghost-root 'addchild ghost)
  (-> (-> ghost 'radius) 'SetValue .035)
  (-> (-> ghost-trans 'translation) 'SetValue x y 0.0)
  (lambda (message)
    (cond ((eq? message 'SetInitial)
	   (lambda (self)
	     (-> (-> ghost-trans 'translation) 'SetValue 0.0 0.0 0.0)))
	  ((eq? message 'setcolor)
	   (lambda (self r g b)
	     (send (send ghost-mat 'diffuseColor) 'SetValue r g b)))
	  ((eq? message 'setLocation)
	   (lambda (self x1 y1 z1)
	     (send (send ghost-trans 'translation) 'SetValue x1 y1 z1)))
	  ((eq? message 'SetRadius)
	   (lambda (self radius)
	     (send (send ghost 'Radius) 'SetValue radius)))
	  ((eq? message 'right)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2))) 	   
	       (if (member (vector->list coord)
			   (list '(0.8 0.4 0.0) 
				 '(0.8 -0.4 0.0) '())) 
   		   (send (send ghost-trans 'translation) 
			 'setValue (- 0.0 x1) y1 z1)			
		   (if (not (member (vector->list coord) right-list))
		       (send (send ghost-trans 'translation) 'setValue 
			     (+ x1 0.1) y1 z1)
		       (send self 'south))))))
	  ((eq? message 'left)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2)))  
	       (if (member (vector->list coord)
			   (list '(-0.8 0.4 0.0) '(-0.8 -0.4 0.0) '()))   
   		   (send (send ghost-trans 'translation) 
			 'setValue (- 0.0 x1) y1 z1)			
		   (if (not (member (vector->list coord) left-list))
		       (send (send ghost-trans 'translation) 'setValue 
			     (- x1 0.1) y1 z1)
		       (send self 'north))))))
	  ((eq? message 'north)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2)))
               (if (not (member (vector->list coord) north-list))
		   (send (send ghost-trans 'translation) 'setValue 
			 x1 (+ y1 0.1) z1)
		   (send self 'right)))))
	  ((eq? message 'south)
	   (lambda (self)
	     (let* ((coord (send self 'getlocation))
		    (x1 (vector-ref coord 0))
		    (y1 (vector-ref coord 1))
		    (z1 (vector-ref coord 2)))
               (if (not (member (vector->list coord) south-list))
		   (send (send ghost-trans 'translation) 'setValue 
			 x1 (- y1 0.1) z1)
		   (send self 'left)))))
	  ((eq? message 'getlocation) 
	   (lambda (self)
	     (let ((coord (-> (-> (-> ghost-trans 'translation) 
				  'GetValue) 'GetValue)))
	       (vector (/ (round (* 10 (vector-ref coord 0))) 10)
		       (/ (round (* 10 (vector-ref coord 1))) 10)
		       (/ (round (* 10 (vector-ref coord 2))) 10))))))))


(define ghost1 (make-ghost 0.1 0.0 1 .4 1))
(define ghost2 (make-ghost -0.1 0.0 1 .4 .4))

(define ghost1-brain   
  (lambda (user-data sensor)
    (let* ((init-coord (send ghost1 'getlocation))
	   (x1 (vector-ref init-coord 0))
	   (y1 (vector-ref init-coord 1))
	   (final-coord (send inventor-man 'getlocation))
	   (x2 (vector-ref final-coord 0))
	   (y2 (vector-ref final-coord 1)))
      (if (not (= (send (send win-text-root 'whichChild) 'getValue) -3))
	  (if (equal? init-coord final-coord)
	      (send (send game-over-root 'whichChild) 'setValue -3)
	      (if (> (abs (- x1 x2)) (abs (- y1 y2)))
		  (if (> x1 x2)
		      (send ghost1 'left)
		      (send ghost1 'right))
		  (if (> y1 y2)
		      (send ghost1 'south)
		      (send ghost1 'north))))))))

;; set up callback

(define callback-info1 (new-SchemeSoCBInfo))
(-> callback-info1 'ref)
(-> (-> callback-info1 'callbackName) 
    'setValue "ghost1-brain")

(define timer-sensor1
  (new-SoTimerSensor (get-scheme-sensor-cb) 
		     (void-cast callback-info1)))

(-> timer-sensor1 'setInterval
    (new-SbTime (/ 1.0 1))) ; repeat 1 times/sec

(define ghost2-brain
  (lambda (user-data sensor)
    (let* ((init-coord (send ghost2 'getlocation))
	   (x1 (vector-ref init-coord 0))
	   (y1 (vector-ref init-coord 1))
	   (final-coord (send inventor-man 'getlocation))
	   (x2 (vector-ref final-coord 0))
	   (y2 (vector-ref final-coord 1)))
      (if (not (= (send (send win-text-root 'whichChild) 'getValue) -3))
	  (if (equal? init-coord final-coord)
	      (send (send game-over-root 'whichChild) 'setValue -3)
	      (if (< (abs (- x1 x2)) (abs (- y1 y2)))
		  (if (> x1 x2)
		      (send ghost2 'left)
		      (send ghost2 'right))
		  (if (> y1 y2)
		      (send ghost2 'south)
		      (send ghost2 'north))))))))

;; set up callback

(define callback-info2 (new-SchemeSoCBInfo))
(-> callback-info2 'ref)
(-> (-> callback-info2 'callbackName) 
    'setValue "ghost2-brain")

(define timer-sensor2
  (new-SoTimerSensor (get-scheme-sensor-cb) 
		     (void-cast callback-info2)))

(-> timer-sensor2 'setInterval
    (new-SbTime (/ 1.0 1))) ; repeat 2 times/sec

(define (put-pellet coord r g b)
  (let* ((x1 (vector-ref coord 0))
	 (y1 (vector-ref coord 1))
         (z1 (vector-ref coord 2)))
    (define pellet (new-SoSeparator))
    (send pellet-node 'addchild pellet)
    (define pellet-trans (new-SoTransform))
    (send pellet 'addchild pellet-trans)
    (define pellet-mat (new-SoMaterial))
    (send pellet 'addchild pellet-mat)
    (define pellet-piece (new-SoCylinder))
    (send pellet 'addchild pellet-piece)
    (send (send pellet-piece 'height) 'setvalue 3)
    (send (send pellet-trans 'translation) 'SetValue x1 y1 z1)
    (send (send pellet-trans 'rotation) 'SetValue 0 0 1 (/ pi 3))
    (send (send pellet-mat 'diffuseColor) 'SetValue r g b)))

(define (put-pellets coord1 coord2 r g b)
  (let* ((x1 (vector-ref coord1 0))
	 (y1 (vector-ref coord1 1))
	 (x2 (vector-ref coord2 0))
	 (y2 (vector-ref coord2 1)))
    (cond ((> x1 x2)
	   (put-pellet coord1 r g b)
	   (put-pellets (vector (- x1 10) y1 0) coord2 r g b))
	  ((< x1 x2)
	   (put-pellet coord1 r g b)
	   (put-pellets (vector (+ x1 10) y1 0) coord2 r g b))
	  ((> y1 y2)
	   (put-pellet coord1 r g b)
	   (put-pellets (vector x1 (- y1 10) 0) coord2 r g b))
	  ((< y1 y2)
	   (put-pellet coord1 r g b)
	   (put-pellets (vector x1 (+ y1 10) 0) coord2 r g b)))))

(load "pellets.scm")



(define (game-over)
  (define root (new-SoSwitch))
  (send root 'ref)
  (define xlate (new-SoTranslation))
  (send (send xlate 'translation) 'setValue -1 0 .15)
  (send root 'addChild xlate)
  (define font (new-SoFont))
  (send (send font 'size) 'setValue .4)
  (send root 'addChild font)
  (define text-mat (new-SoMaterial))
  (send (send text-mat 'diffuseColor) 'setValue 0 0.5 0)
  (send root 'addChild text-mat)
  (define text (new-SoText3))
  (send root 'addChild text)
  (send (send text 'string) 'set1Value 0 (new-SbString "Game Over"))
  (send root 'unrefNoDelete)
  root)

(define (build-new-game-text)
  (define root (new-SoSelection))
  (send root 'ref)
  (send (send root 'policy) 'setValue SoSelection::ENUM_TOGGLE)
  (define text-pick-style (new-SoPickStyle))
  (send (send text-pick-style 'style) 'setValue SoPickStyle::BOUNDING_BOX)
  (send root 'addChild text-pick-style)
  (define xlate (new-SoTranslation))
  (send (send xlate 'translation) 'setValue .2 .8 .2)
  (send root 'addChild xlate)
  (define font (new-SoFont))
  (send (send font 'size) 'setValue .2)
  (send root 'addChild font)
  (define text-mat (new-SoMaterial))
  (send (send text-mat 'diffuseColor) 'setValue 0.0 0.5 0.0)
  (send root 'addChild text-mat)
  (define text (new-SoText3))
  (send root 'addChild text)
  (send (send text 'string) 'set1Value 0 (new-SbString "New Game"))
  (define cb-info (new-SchemeSoCBInfo))
  (send cb-info 'ref)
  (send (send cb-info 'callbackName) 'setValue "new-game-cb")
  (send root 'addSelectionCallback (get-scheme-selection-path-cb) (void-cast cb-info))
  (send root 'addDeselectionCallback (get-scheme-selection-path-cb) (void-cast cb-info))
  (send root 'unrefNoDelete)
  root)

(define new-game-text-root (build-new-game-text))
(send root 'addChild new-game-text-root)

(define (new-game-cb user-data path)
  (new-game))

(define game-over-root (game-over))
(send root 'addChild game-over-root) 

(define (win-text)
  (define root (new-SoSwitch))
  (send root 'ref)
  (define xlate (new-SoTranslation))
  (send (send xlate 'translation) 'setValue -.8 0 .15)
  (send root 'addChild xlate)
  (define font (new-SoFont))
  (send (send font 'size) 'setValue .4)
  (send root 'addChild font)
  (define text-mat (new-SoMaterial))
  (send (send text-mat 'diffuseColor) 'setValue 0 0.5 0)
  (send root 'addChild text-mat)
  (define text (new-SoText3))
  (send root 'addChild text)
  (send (send text 'string) 'set1Value 0 (new-SbString "You Won"))
  (send root 'unrefNoDelete)
  root)

(define win-text-root (win-text))
(send root 'addChild win-text-root) 

(define (win)
  (send (send win-text-root 'whichChild) 'SetValue -3))
	   
(define (win? coord)
   (if (> counter 133)
       (win)
       (if (not (member coord winlist))
	   (begin
	     (set! winlist (cons coord winlist))
	     (set! counter (+ counter 1))
	     (if (> counter 133)
		 (win))))))

(define (start-game)
  (send ghost1 'left)
  (send ghost1 'north)
  (send ghost1 'north)
  (send ghost1 'north)
  (-> Viewer 'render)
  (-> timer-sensor1 'schedule)
  (send ghost2 'right)
  (send ghost2 'north)
  (send ghost2 'north)
  (send ghost2 'north)
  (-> Viewer 'render)
  (-> timer-sensor2 'schedule))

(define (new-game)
  (send inventor-man 'setInitial)
  (send ghost1 'setLocation 0.1 0.0 0.0)
  (send ghost2 'setLocation -0.1 0.0 0.0)
  (load "pellets.scm")
  (set! counter 0)
  (set! winlist '())
  (send (send game-over-root 'whichChild) 'setValue -1)
  (send (send win-text-root 'whichChild) 'setValue -1)
  (start-game))

(start-game)
maze.scm
(define maze (new-SoSeparator))
(-> root 'addchild maze)
(define scale (new-SoScale))
(-> maze 'addchild scale)
(-> (-> scale 'scaleFactor) 'SetValue .05 .05 .05)
(define maze-mat (new-SoMaterial))
(-> maze 'addchild maze-mat)
(define maze-1 (new-SoSeparator))
(-> maze 'addchild maze-1)
(define maze1-trans (new-SoTransform))
(-> maze-1 'addchild maze1-trans)
(define maze-piece1 (new-SoCube))
(-> maze-1 'addchild maze-piece1)
(-> (-> maze-piece1 'height) 'SetValue 8)
(-> (-> maze1-trans 'translation) 'SetValue -16 -13 0)
(define maze-2 (new-SoSeparator))
(-> maze 'addchild maze-2)
(define maze2-trans (new-SoTransform))
(-> maze-2 'addchild maze2-trans)
(define maze-piece2 (new-SoCube))
(-> maze-2 'addchild maze-piece2)
(-> (-> maze-piece2 'height) 'SetValue 8)
(-> (-> maze2-trans 'translation) 'SetValue 16 -13 0)
(define maze-3 (new-SoSeparator))
(-> maze 'addchild maze-3)
(define maze3-trans (new-SoTransform))
(-> maze-3 'addchild maze3-trans)
(define maze-piece3 (new-SoCube))
(-> maze-3 'addchild maze-piece3)
(-> (-> maze-piece3 'width) 'SetValue 34)
(-> (-> maze3-trans 'translation) 'SetValue 0 16 0)
(define maze-4 (new-SoSeparator))
(-> maze 'addchild maze-4)      
(define maze4-trans (new-SoTransform))
(-> maze-4 'addchild maze4-trans)
(define maze-piece4 (new-SoCube))
(-> maze-4 'addchild maze-piece4)
(-> (-> maze-piece4 'width) 'SetValue 34)
(-> (-> maze4-trans 'translation) 'SetValue 0 -16 0)
(define maze-5 (new-SoSeparator))
(-> maze 'addchild maze-5)      
(define maze5-trans (new-SoTransform))
(-> maze-5 'addchild maze5-trans)
(define maze-piece5 (new-SoCube))
(-> maze-5 'addchild maze-piece5)
(-> (-> maze-piece5 'width) 'SetValue 6)
(-> (-> maze5-trans 'translation) 'SetValue 12 0 0)
(define maze-6 (new-SoSeparator))
(-> maze 'addchild maze-6)      
(define maze6-trans (new-SoTransform))
(-> maze-6 'addchild maze6-trans)
(define maze-piece6 (new-SoCube))
(-> maze-6 'addchild maze-piece6)
(-> (-> maze-piece6 'width) 'SetValue 6)
(-> (-> maze6-trans 'translation) 'SetValue -12 0 0)
(define maze-7 (new-SoSeparator))
(-> maze 'addchild maze-7)      
(define maze7-trans (new-SoTransform))
(-> maze-7 'addchild maze7-trans)
(define maze-piece7 (new-SoCube))
(-> maze-7 'addchild maze-piece7)
(-> (-> maze7-trans 'translation) 'SetValue  0 14 0)
(define maze-8 (new-SoSeparator))
(-> maze 'addchild maze-8)      
(define maze8-trans (new-SoTransform))
(-> maze-8 'addchild maze8-trans)
(define maze-piece8 (new-SoCube))
(-> maze-8 'addchild maze-piece8)
(-> (-> maze8-trans 'translation) 'SetValue 0 -14 0)
(define maze-9 (new-SoSeparator))
(-> maze 'addchild maze-9)      
(define maze9-trans (new-SoTransform))
(-> maze-9 'addchild maze9-trans)
(define maze-piece9 (new-SoCube))
(-> maze-9 'addchild maze-piece9)
(-> (-> maze-piece9 'width) 'SetValue 14)
(-> (-> maze9-trans 'translation) 'SetValue 0 -4 0)
(define maze-10 (new-SoSeparator))
(-> maze 'addchild maze-10)      
(define maze10-trans (new-SoTransform))
(-> maze-10 'addchild maze10-trans)
(define maze-piece10 (new-SoCube))
(-> maze-10 'addchild maze-piece10)
(-> (-> maze-piece10 'height) 'SetValue 8)
(-> (-> maze10-trans 'translation) 'SetValue 6 1 0)   
(define maze-11 (new-SoSeparator))
(-> maze 'addchild maze-11)      
(define maze11-trans (new-SoTransform))
(-> maze-11 'addchild maze11-trans)
(define maze-piece11 (new-SoCube))
(-> maze-11 'addchild maze-piece11)
(-> (-> maze-piece11 'height) 'SetValue 8)
(-> (-> maze11-trans 'translation) 'SetValue -6 1 0)
(define maze11-trans (new-SoTransform))   
(define maze-12 (new-SoSeparator))
(-> maze 'addchild maze-12)      
(define maze12-trans (new-SoTransform))
(-> maze-12 'addchild maze12-trans)
(define maze-piece12 (new-SoCube))
(-> maze-12 'addchild maze-piece12)
(-> (-> maze-piece12 'width) 'SetValue 4)
(-> (-> maze12-trans 'translation) 'SetValue -3 4 0)
(define maze12-trans (new-SoTransform))   
(define maze-13 (new-SoSeparator))
(-> maze 'addchild maze-13)      
(define maze13-trans (new-SoTransform))
(-> maze-13 'addchild maze13-trans)
(define maze-piece13 (new-SoCube))
(-> maze-13 'addchild maze-piece13)
(-> (-> maze-piece13 'width) 'SetValue 4)
(-> (-> maze13-trans 'translation) 'SetValue 3 4 0)
(define maze-14 (new-SoSeparator))
(-> maze 'addchild maze-14)      
(define maze14-trans (new-SoTransform))
(-> maze-14 'addchild maze14-trans)
(define maze-piece14 (new-SoCube))
(-> maze-14 'addchild maze-piece14)
(-> (-> maze-piece14 'height) 'SetValue 6)
(-> (-> maze14-trans 'translation) 'SetValue 12 10 0)
(define maze-15 (new-SoSeparator))
(-> maze 'addchild maze-15)      
(define maze15-trans (new-SoTransform))
(-> maze-15 'addchild maze15-trans)
(define maze-piece15 (new-SoCube))
(-> maze-15 'addchild maze-piece15)
(-> (-> maze-piece15 'height) 'SetValue 6)
(-> (-> maze15-trans 'translation) 'SetValue 12 -10 0)
(define maze-16 (new-SoSeparator))
(-> maze 'addchild maze-16)      
(define maze16-trans (new-SoTransform))
(-> maze-16 'addchild maze16-trans)
(define maze-piece16 (new-SoCube))
(-> maze-16 'addchild maze-piece16)
(-> (-> maze-piece16 'height) 'SetValue 6)
(-> (-> maze16-trans 'translation) 'SetValue -12 10 0)
(define maze-17 (new-SoSeparator))
(-> maze 'addchild maze-17)      
(define maze17-trans (new-SoTransform))
(-> maze-17 'addchild maze17-trans)
(define maze-piece17 (new-SoCube))
(-> maze-17 'addchild maze-piece17)
(-> (-> maze-piece17 'height) 'SetValue 6)
(-> (-> maze17-trans 'translation) 'SetValue  -12 -10 0)
(define maze-18 (new-SoSeparator))
(-> maze 'addchild maze-18)      
(define maze18-trans (new-SoTransform))
(-> maze-18 'addchild maze18-trans)
(define maze-piece18 (new-SoCube))
(-> maze-18 'addchild maze-piece18)
(-> (-> maze-piece18 'width) 'SetValue 6)
(-> (-> maze18-trans 'translation) 'SetValue  0 8 0)
(define maze-19 (new-SoSeparator))
(-> maze 'addchild maze-19)      
(define maze19-trans (new-SoTransform))
(-> maze-19 'addchild maze19-trans)
(define maze-piece19 (new-SoCube))
(-> maze-19 'addchild maze-piece19)
(-> (-> maze-piece19 'width) 'SetValue 6)
(-> (-> maze19-trans 'translation) 'SetValue 0 -8 0)
(define maze-20 (new-SoSeparator))
(-> maze 'addchild maze-20)      
(define maze20-trans (new-SoTransform))
(-> maze-20 'addchild maze20-trans)
(define maze-piece20 (new-SoCube))
(-> maze-20 'addchild maze-piece20)
(-> (-> maze-piece20 'width) 'SetValue 4)
(-> (-> maze20-trans 'translation) 'SetValue 11 4 0)
(define maze-21 (new-SoSeparator))
(-> maze 'addchild maze-21)      
(define maze21-trans (new-SoTransform))
(-> maze-21 'addchild maze21-trans)
(define maze-piece21 (new-SoCube))
(-> maze-21 'addchild maze-piece21)
(-> (-> maze-piece21 'width) 'SetValue 4)
(-> (-> maze21-trans 'translation) 'SetValue 11 -4 0)
(define maze-22 (new-SoSeparator))
(-> maze 'addchild maze-22)      
(define maze22-trans (new-SoTransform))
(-> maze-22 'addchild maze22-trans)
(define maze-piece22 (new-SoCube))
(-> maze-22 'addchild maze-piece22)
(-> (-> maze-piece22 'width) 'SetValue 4)
(-> (-> maze22-trans 'translation) 'SetValue -11 -4 0)
(define maze-23 (new-SoSeparator))
(-> maze 'addchild maze-23)      
(define maze23-trans (new-SoTransform))
(-> maze-23 'addchild maze23-trans)
(define maze-piece23 (new-SoCube))
(-> maze-23 'addchild maze-piece23)
(-> (-> maze-piece23 'width) 'SetValue 4)
(-> (-> maze23-trans 'translation) 'SetValue -11 4 0)
(define maze-24 (new-SoSeparator))
(-> maze 'addchild maze-24)      
(define maze24-trans (new-SoTransform))
(-> maze-24 'addchild maze24-trans)
(define maze-piece24 (new-SoCube))
(-> maze-24 'addchild maze-piece24)
(-> (-> maze-piece24 'width) 'SetValue 4)
(-> (-> maze24-trans 'translation) 'SetValue 7 8 0)
(define maze-25 (new-SoSeparator))
(-> maze 'addchild maze-25)      
(define maze25-trans (new-SoTransform))
(-> maze-25 'addchild maze25-trans)
(define maze-piece25 (new-SoCube))
(-> maze-25 'addchild maze-piece25)
(-> (-> maze-piece25 'width) 'SetValue 4)
(-> (-> maze25-trans 'translation) 'SetValue -7 8 0)
(define maze-26 (new-SoSeparator))
(-> maze 'addchild maze-26)      
(define maze26-trans (new-SoTransform))
(-> maze-26 'addchild maze26-trans)
(define maze-piece26 (new-SoCube))
(-> maze-26 'addchild maze-piece26)
(-> (-> maze-piece26 'width) 'SetValue 4)
(-> (-> maze26-trans 'translation) 'SetValue -7 -8 0)
(define maze-27 (new-SoSeparator))
(-> maze 'addchild maze-27)      
(define maze27-trans (new-SoTransform))
(-> maze-27 'addchild maze27-trans)
(define maze-piece27 (new-SoCube))
(-> maze-27 'addchild maze-piece27)
(-> (-> maze-piece27 'width) 'SetValue 4)
(-> (-> maze27-trans 'translation) 'SetValue 7 -8 0)
(define maze-28 (new-SoSeparator))
(-> maze 'addchild maze-28)      
(define maze28-trans (new-SoTransform))
(-> maze-28 'addchild maze28-trans)
(define maze-piece28 (new-SoCube))
(-> maze-28 'addchild maze-piece28)
(-> (-> maze-piece28 'width) 'SetValue 4)
(-> (-> maze28-trans 'translation) 'SetValue 5 12 0)
(define maze-29 (new-SoSeparator))
(-> maze 'addchild maze-29)      
(define maze29-trans (new-SoTransform))
(-> maze-29 'addchild maze29-trans)
(define maze-piece29 (new-SoCube))
(-> maze-29 'addchild maze-piece29)
(-> (-> maze-piece29 'width) 'SetValue 4)
(-> (-> maze29-trans 'translation) 'SetValue -5 12 0)
(define maze-30 (new-SoSeparator))
(-> maze 'addchild maze-30)      
(define maze30-trans (new-SoTransform))
(-> maze-30 'addchild maze30-trans)
(define maze-piece30 (new-SoCube))
(-> maze-30 'addchild maze-piece30)
(-> (-> maze-piece30 'width) 'SetValue 4)
(-> (-> maze30-trans 'translation) 'SetValue 5 -12 0)
(define maze-31 (new-SoSeparator))
(-> maze 'addchild maze-31)      
(define maze31-trans (new-SoTransform))
(-> maze-31 'addchild maze31-trans)
(define maze-piece31 (new-SoCube))
(-> maze-31 'addchild maze-piece31)
(-> (-> maze-piece31 'width) 'SetValue 4)
(-> (-> maze31-trans 'translation) 'SetValue -5 -12 0)
(define maze-32 (new-SoSeparator))
(-> maze 'addchild maze-32)      
(define maze32-trans (new-SoTransform))
(-> maze-32 'addchild maze32-trans)
(define maze-piece32 (new-SoCube))
(-> maze-32 'addchild maze-piece32)
(-> (-> maze32-trans 'translation) 'SetValue 10 12 0)
(define maze-33 (new-SoSeparator))
(-> maze 'addchild maze-33)      
(define maze33-trans (new-SoTransform))
(-> maze-33 'addchild maze33-trans)
(define maze-piece33 (new-SoCube))
(-> maze-33 'addchild maze-piece33)
(-> (-> maze33-trans 'translation) 'SetValue -10 12 0)
(define maze-34 (new-SoSeparator))
(-> maze 'addchild maze-34)      
(define maze34-trans (new-SoTransform))
(-> maze-34 'addchild maze34-trans)
(define maze-piece34 (new-SoCube))
(-> maze-34 'addchild maze-piece34)
(-> (-> maze34-trans 'translation) 'SetValue -10 -12 0)
(define maze-35 (new-SoSeparator))
(-> maze 'addchild maze-35)      
(define maze35-trans (new-SoTransform))
(-> maze-35 'addchild maze35-trans)
(define maze-piece35 (new-SoCube))
(-> maze-35 'addchild maze-piece35)
(-> (-> maze35-trans 'translation) 'SetValue 10 -12 0)
(define maze-36 (new-SoSeparator))
(-> maze 'addchild maze-36)      
(define maze36-trans (new-SoTransform))
(-> maze-36 'addchild maze36-trans)
(define maze-piece36 (new-SoCube))
(-> maze-36 'addchild maze-piece36)
(-> (-> maze36-trans 'translation) 'SetValue 0 10 0)

(define maze-37 (new-SoSeparator))
(-> maze 'addchild maze-37)      
(define maze37-trans (new-SoTransform))
(-> maze-37 'addchild maze37-trans)
(define maze-piece37 (new-SoCube))
(-> maze-37 'addchild maze-piece37)
(-> (-> maze37-trans 'translation) 'SetValue 0 -10 0)

(define maze-38 (new-SoSeparator))
(-> maze 'addchild maze-38) 
(define maze38-trans (new-SoTransform))
(-> maze-38 'addchild maze38-trans)
(define maze-piece38 (new-SoCube))
(-> maze-38 'addchild maze-piece38)
(-> (-> maze-piece38 'height) 'SetValue 14)
(-> (-> maze38-trans 'translation) 'SetValue -16 0 0)

(define maze-39 (new-SoSeparator))
(-> maze 'addchild maze-39)
(define maze39-trans (new-SoTransform))
(-> maze-39 'addchild maze39-trans)
(define maze-piece39 (new-SoCube))
(-> maze-39 'addchild maze-piece39)
(-> (-> maze-piece39 'height) 'SetValue 14)
(-> (-> maze39-trans 'translation) 'SetValue 16 0 0)

(define maze-40 (new-SoSeparator))
(-> maze 'addchild maze-40) 
(define maze40-trans (new-SoTransform))
(-> maze-40 'addchild maze40-trans)
(define maze-piece40 (new-SoCube))
(-> maze-40 'addchild maze-piece40)
(-> (-> maze-piece40 'height) 'SetValue 8)
(-> (-> maze40-trans 'translation) 'SetValue 16 13 0)

(define maze-41 (new-SoSeparator))
(-> maze 'addchild maze-41)
(define maze41-trans (new-SoTransform))
(-> maze-41 'addchild maze41-trans)
(define maze-piece41 (new-SoCube))
(-> maze-41 'addchild maze-piece41)
(-> (-> maze-piece41 'height) 'SetValue 8)
(-> (-> maze41-trans 'translation) 'SetValue -16 13 0)
pellets.scm
(put-pellets (vector 40 20 0) (vector 40 -30 0) 1 1 1)
(put-pellets (vector -70 -70 0) (vector -70 0 0) 1 1 1)
(put-pellets (vector -70 10 0) (vector -70 80 0) 1 1 1)
(put-pellets (vector 70 -70 0) (vector 70 0 0) 1 1 1)
(put-pellets (vector 70 10 0) (vector 70 80 0) 1 1 1)
(put-pellets (vector 10 -70 0) (vector 80 -70 0) 1 1 1)
(put-pellets (vector -10 -70 0) (vector -80 -70 0) 1 1 1)
(put-pellets (vector 10 70 0) (vector 80 70 0) 1 1 1)
(put-pellets (vector -10 70 0) (vector -80 70 0) 1 1 1)
(put-pellets (vector -60 -30 0) (vector 0 -30 0) 1 1 1)
(put-pellets (vector 10 -30 0) (vector 70 -30 0) 1 1 1)
(put-pellets (vector -60 30 0) (vector 70 30 0) 1 1 1)
(put-pellets (vector -40 -20 0) (vector -40 30 0) 1 1 1)
(put-pellets (vector -50 -50 0) (vector 0 -50 0) 1 1 1)
(put-pellets (vector  50 -50 0) (vector 0 -50 0) 1 1 1)
(put-pellets (vector -50 50 0) (vector 0 50 0) 1 1 1)
(put-pellets (vector  50 50 0) (vector 0 50 0) 1 1 1)
(put-pellet (vector -40 -60 0) 1 1 1)
(put-pellet (vector 40 -60 0) 1 1 1)
(put-pellets (vector  -10 -60 0) (vector 20 -60 0) 1 1 1)
(put-pellet (vector -40 60 0) 1 1 1)
(put-pellet (vector 40 60 0) 1 1 1)
(put-pellets (vector  -10 60 0) (vector 20 60 0) 1 1 1)
(put-pellet (vector -50 -40 0) 1 1 1)
(put-pellet (vector 50 -40 0) 1 1 1)
(put-pellet (vector -20 -40 0) 1 1 1)
(put-pellet (vector 20 -40 0) 1 1 1)
(put-pellet (vector -50 40 0) 1 1 1)
(put-pellet (vector 50 40 0) 1 1 1)
(put-pellet (vector -20 40 0) 1 1 1)
(put-pellet (vector 20 40 0) 1 1 1)
(put-pellets (vector -60 -10 0) (vector -40 -10 0) 1 1 1)
(put-pellets (vector 60 -10 0) (vector 40 -10 0) 1 1 1)
(put-pellets (vector -60 10 0) (vector -40 10 0) 1 1 1)
(put-pellets (vector 60 10 0) (vector 40 10 0) 1 1 1)
Peanuts! - Andrew Samnick and Valentin Spitkovsky

"Peanuts!" is a game of strategy and skill. It is a two-player game, in which players sequentially eat peanuts. When a peanut is selected, all the peanuts above and to the right of it in the array disappear. Whoever eats the rotten peanut in the lower left corner, loses. Good luck!

Download the source code and related files

peanuts.c++

/*******************************************************************************/
/*                                                                             */
/*                                                                             */
/* Program: Peanuts!                                                           */
/*                                                                             */
/* Description: ``Peanuts!'' is a game of strategy and skill.                  */
/*              It is a two-player game, in which players sequentially         */
/*              eat peanuts.  When a peanut is selected, all the peanuts       */
/*              above and to the right of it in the array disappear.           */
/*              Whoever eats the rotten peanut in the lower left               */
/*              corner loses.                                                  */
/*                                                                             */
/*                                                                             */
/*******************************************************************************/
/*******************************************************************************/
/*                                                                             */
/*                                                                             */
/* Authors: Andrew Samnick and Valentin I. Spitkovsky                          */
/*                                                                             */
/* Final Project:    Computer Graphics Workshop                                */
/*                      MIT Media Laboratory                                   */
/*                       Kenneth B. Russell                                    */
/*                                                                             */
/* Date: 02/02/95                                                              */
/*                                                                             */
/* Version: 1.0                                                                */
/*                                                                             */
/*                                                                             */
/*******************************************************************************/

#include <Inventor/SoDB.h>

#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/viewers/SoXtExaminerViewer.h>

#include <Inventor/events/SoMouseButtonEvent.h>

#include <Inventor/sensors/SoIdleSensor.h>
#include <Inventor/sensors/SoTimerSensor.h>

#include <Inventor/nodes/SoCone.h>
#include <Inventor/nodes/SoCube.h>
#include <Inventor/nodes/SoFont.h>
#include <Inventor/nodes/SoText3.h>
#include <Inventor/nodes/SoGroup.h>
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoPerspectiveCamera.h>
#include <Inventor/nodes/SoTexture2.h>
#include <Inventor/nodes/SoRotation.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoSelection.h>
#include <Inventor/nodes/SoTransform.h>
#include <Inventor/nodes/SoEventCallback.h>
#include <Inventor/nodes/SoDirectionalLight.h>
p
#include <string.h>

#define MAX_M (10)
#define MAX_N (10)

#define RADIUS (5)
#define SHIFT (20)

SoXtExaminerViewer *viewer;

SoSelection *quitRoot, *gameRoot, *setupRoot;
SoSeparator *startRoot;

SoSeparator     *group[MAX_M][MAX_N];
SoSphere       *sphere[MAX_M][MAX_N];
SoMaterial   *material[MAX_M][MAX_N];
SoTransform *transform[MAX_M][MAX_N], *horShift, *allShift;

SoTimerSensor *start_rot_sens, *gover_rot_sens;

SoText3 *turn, *winner_name, *horVal, *verVal;

int M=5, N=5;

void startCB (void *, SoEventCallback *eventCB)
{
  const SoEvent *event = eventCB->getEvent ();

  if (SO_MOUSE_PRESS_EVENT (event, ANY))
    {
     eventCB->setHandled();
     viewer->setSceneGraph (setupRoot);
    }
}

void start_rotateCB (void *data, SoSensor *)
{
  SoRotation *rot = (SoRotation *)data;

  SbRotation curRot = rot->rotation.getValue ();
  curRot = SbRotation (SbVec3f (0, 1, 0), M_PI/12.0) * curRot;
  rot->rotation.setValue (curRot);
}

void make_startRoot (void)
{
  startRoot = new SoSeparator;
  startRoot->ref ();

  SoPerspectiveCamera *camera = new SoPerspectiveCamera;
  camera->position.setValue (-10.538795, -1.634, 275);
  startRoot->addChild (camera);
  startRoot->addChild (new SoDirectionalLight);

  SoEventCallback *eventCB = new SoEventCallback;
  eventCB->addEventCallback 
    (SoMouseButtonEvent::getClassTypeId (), startCB,
     viewer->getSceneManager ()->getSceneGraph ());
  startRoot->addChild (eventCB);

  SoSeparator *face = new SoSeparator;
  startRoot->addChild (face);

  SoTransform *trans0 = new SoTransform;
  trans0->translation.setValue (-75, -5, 0);
  face->addChild (trans0);

  SoTexture2 *texture = new SoTexture2;
  texture->filename.setValue ("coolpnut.rgb");
  face->addChild (texture);
 
  SoRotation *start_rot = new SoRotation;
  face->addChild (start_rot);

  start_rot_sens = 
    new SoTimerSensor (start_rotateCB, start_rot);
  start_rot_sens->schedule ();

  SoTransform *trans1 = new SoTransform;
  trans1->rotation.setValue (SbVec3f (1, 0, 0), -M_PI/6);
  face->addChild (trans1);

  SoCube *cube = new SoCube;
  cube->height.setValue (50);
  cube->width.setValue (50);
  cube->depth.setValue (50);
  face->addChild (cube);  

  SoSeparator *credits = new SoSeparator;
  startRoot->addChild (credits);

  SoTransform *trans2 = new SoTransform;
  trans2->translation.setValue (50, 0, 0);
  trans2->rotation.setValue (SbVec3f (0, 1, 0), -M_PI/6);
  credits->addChild (trans2);     

  SoSeparator *big = new SoSeparator;
  credits->addChild (big);

  SoFont *big_font = new SoFont;
  big_font->name.setValue ("Times-Roman");
  big_font->size.setValue (30);
  big->addChild (big_font);

  SoTexture2 *texture2 = new SoTexture2;
  texture2->filename.setValue ("nutture.rgb");
  big->addChild (texture2);

  SoText3 *game = new SoText3;
  game->parts = SoText3::ALL;
  game->string.setValue ("Peanuts!");
  game->justification.setValue (SoText3::CENTER);
  big->addChild (game);

  SoTransform *ntrans = new SoTransform;
  ntrans->translation.setValue (0, 50, 0);
  credits->addChild (ntrans);

  SoFont *small_font1 = new SoFont;
  small_font1->name.setValue ("Times-Roman");
  small_font1->size.setValue (10);
  credits->addChild (small_font1);

  SoText3 *names = new SoText3;
  names->parts = SoText3::ALL;
  names->string.setValue ("Drew Samnick & Val Spitkovsky");
  names->justification.setValue (SoText3::CENTER);
  credits->addChild (names);

  SoTransform *ctrans = new SoTransform;
  ctrans->translation.setValue (0, -90, 0);
  credits->addChild (ctrans);

  SoFont *small_font2 = new SoFont;
  small_font2->name.setValue ("Times-Roman");
  small_font2->size.setValue (5);
  credits->addChild (small_font2);

  SoText3 *course = new SoText3;
  course->parts = SoText3::ALL;
  course->string.set1Value (0, "Computer Graphics Workshop '96");
  course->string.set1Value (1, "MIT Media Laboratory");
  course->string.set1Value (2, "Kenneth B. Russell");
  course->string.set1Value (3, "Final Project");
  course->string.set1Value (4, "02/02/96");
  course->justification.setValue (SoText3::CENTER);
  credits->addChild (course);
}

void gover_rotateCB (void *data, SoSensor *)
{
  SoRotation *rot = (SoRotation *)data;

  SbRotation curRot = rot->rotation.getValue ();
  curRot = SbRotation (SbVec3f (0, 1, 0), M_PI/18.0) * curRot;
  rot->rotation.setValue (curRot);
}

void peanutquit_sCB (void *, SoPath *selectionPath)
{
  SoSphere *ourBall;
  char name[16];

  if (selectionPath->getTail ()->
    isOfType (SoSphere::getClassTypeId ()))
      {
       ourBall = (SoSphere*) selectionPath->getTail ();
       strcpy (name, ourBall->getName ().getString ());

       if (strcmp ("QUIT", name) == 0) exit (0);
       if (strcmp ("AGAIN", name) == 0) 
	 {
	   gover_rot_sens->unschedule();
	   viewer->setSceneGraph (setupRoot);
	 }
      }

  quitRoot->deselect (selectionPath->getTail ());
}

void make_quitRoot (void)
{
  quitRoot = new SoSelection;
  quitRoot->ref ();
  quitRoot->addSelectionCallback (peanutquit_sCB);

  SoPerspectiveCamera *camera = new SoPerspectiveCamera;
  camera->position.setValue (-1.26, -9, 250);
  quitRoot->addChild (camera);
  quitRoot->addChild (new SoDirectionalLight);

  SoSeparator *face = new SoSeparator;
  quitRoot->addChild (face);

  SoSeparator *winner = new SoSeparator;
  quitRoot->addChild (winner);

  SoFont *winner_font = new SoFont;
  winner_font->name.setValue ("Times-Roman");
  winner_font->size.setValue (20);
  winner->addChild (winner_font);

  SoTransform *winner_trans = new SoTransform;
  winner_trans->translation.setValue (0, 50, 0);
  winner_trans->rotation.setValue (SbVec3f (0, 1, 0), M_PI/6);
  winner->addChild (winner_trans);

  winner_name = new SoText3;
  winner_name->parts = SoText3::ALL;
  winner_name->justification.setValue (SoText3::CENTER);
  winner->addChild (winner_name);

  SoSeparator *gover_sep = new SoSeparator;
  quitRoot->addChild (gover_sep);

  SoFont *gover_font = new SoFont;
  gover_font->name.setValue ("Times-Roman");
  gover_font->size.setValue (40);
  gover_sep->addChild (gover_font);

  SoRotation *gover_rot = new SoRotation;
  gover_sep->addChild (gover_rot);

  gover_rot_sens = 
    new SoTimerSensor (gover_rotateCB, gover_rot);

  SoTransform *gover_trans = new SoTransform;
  gover_trans->rotation.setValue (SbVec3f (1, 0, 0), -M_PI/6);
  gover_sep->addChild (gover_trans);

  SoText3 *gover_text = new SoText3;
  gover_text->parts = SoText3::ALL;
  gover_text->string.setValue ("Game Over!");
  gover_text->justification.setValue (SoText3::CENTER);
  gover_sep->addChild (gover_text);  

  SoFont *rest_font = new SoFont;
  rest_font->name.setValue ("Times-Roman");
  rest_font->size.setValue (10);
  quitRoot->addChild (rest_font);

  SoTransform *rest_trans = new SoTransform;
  rest_trans->rotation.setValue (SbVec3f (0, 1, 0), M_PI/6);
  quitRoot->addChild (rest_trans);

  SoSeparator *pagain_sep = new SoSeparator;
  quitRoot->addChild (pagain_sep);

  SoTransform *pagain_trans = new SoTransform;
  pagain_trans->translation.setValue (0, -40, 0);
  pagain_sep->addChild (pagain_trans);

  SoText3 *pagain_text = new SoText3;
  pagain_text->parts = SoText3::ALL;
  pagain_text->string.setValue ("Would you like to play again?");
  pagain_text->justification.setValue (SoText3::CENTER);
  pagain_sep->addChild (pagain_text);

  SoTexture2 *texture = new SoTexture2;
  texture->filename.setValue ("nutture.rgb");
  quitRoot->addChild (texture);

  SoSeparator *yes_sep = new SoSeparator;
  quitRoot->addChild (yes_sep);

  SoTransform *yes_trans = new SoTransform;
  yes_trans->translation.setValue (0, -60, 0);
  yes_sep->addChild (yes_trans);
    
  SoText3 *yes_text = new SoText3;
  yes_text->parts = SoText3::ALL;
  yes_text->string.setValue ("Yes");
  yes_text->justification.setValue (SoText3::CENTER);
  yes_sep->addChild (yes_text);

  SoMaterial *yes_mat = new SoMaterial;
  yes_mat->diffuseColor.setValue (.9, .8, 0);
  yes_sep->addChild (yes_mat);

  SoTransform *yesb_trans = new SoTransform;
  yesb_trans->translation.setValue (-15, 2.5, 0);
  yes_sep->addChild (yesb_trans);

  SoSphere *yes_ball = new SoSphere;
  yes_ball->setName ("AGAIN");
  yes_ball->radius.setValue (5);
  yes_sep->addChild (yes_ball);
  
  SoSeparator *no_sep = new SoSeparator;
  quitRoot->addChild (no_sep);

  SoTransform *no_trans = new SoTransform;
  no_trans->translation.setValue (0, -75, 0);
  no_sep->addChild (no_trans);
    
  SoText3 *no_text = new SoText3;
  no_text->parts = SoText3::ALL;
  no_text->string.setValue ("No");
  no_text->justification.setValue (SoText3::CENTER);
  no_sep->addChild (no_text);

  SoMaterial *no_mat = new SoMaterial;
  no_mat->diffuseColor.setValue (0, .8, .9);
  no_sep->addChild (no_mat);

  SoTransform *nob_trans = new SoTransform;
  nob_trans->translation.setValue (-15, 2.5, 0);
  no_sep->addChild (nob_trans);

  SoSphere *no_ball = new SoSphere;
  no_ball->setName ("QUIT");
  no_ball->radius.setValue (5);
  no_sep->addChild (no_ball);  
}

void peanut_sCB (void *, SoPath *selectionPath)
{
  SoSphere *eatenPeanut;
  char name[256];
  int x, y, i, j;

  if (selectionPath->getTail ()->
    isOfType (SoSphere::getClassTypeId ()))
      {
       eatenPeanut = (SoSphere*) selectionPath->getTail ();
       strcpy (name, eatenPeanut->getName ().getString ());
       sscanf (name, "_%d_%d", &x, &y);

       for (i=x; i<M; i++)
         for (j=y; j<N; j++)
           sphere[i][j]->radius.setValue (0);

       strcpy (name, turn->getName ().getString ());

       if (x==0 && y==0)
         {
          if (strcmp (name, "Player_1_Up") == 0)
            winner_name->string.setValue ("Player 2 Wins!!!");
          else
            winner_name->string.setValue ("Player 1 Wins!!!");

	  gover_rot_sens->schedule();
          viewer->setSceneGraph (quitRoot);
         }
       else
         {
          if (strcmp (name, "Player_1_Up") == 0)
            {
             turn->string.setValue ("Player 2 Up");
             turn->setName ("Player_2_Up");
            }
          else
            {
             turn->string.setValue ("Player 1 Up");
             turn->setName ("Player_1_Up");
            }
         }
      }

  gameRoot->deselect (selectionPath->getTail ());
}

void make_gameRoot (void)
{
  int m, n;
  char name[8];

  gameRoot = new SoSelection;
  gameRoot->ref ();
  gameRoot->addSelectionCallback (peanut_sCB);

  SoPerspectiveCamera *camera = new SoPerspectiveCamera;
  camera->position.setValue (-5, 71.2, 325);
  gameRoot->addChild (camera);
  gameRoot->addChild (new SoDirectionalLight);

  allShift = new SoTransform;
  gameRoot->addChild (allShift);

  SoSeparator *who = new SoSeparator;
  gameRoot->addChild (who);

  SoTransform *PlayerTrans = new SoTransform;
  PlayerTrans->translation.setValue (0, -2*SHIFT, 0);
  PlayerTrans->rotation.setValue (SbVec3f (1, 0, 0), -M_PI/6);
  who->addChild (PlayerTrans);

  turn = new SoText3;
  turn->parts = SoText3::ALL;
  turn->justification.setValue (SoText3::CENTER);
  turn->string.setValue ("Player 1 Up");
  turn->setName ("Player_1_Up");
  who->addChild (turn);

  SoTexture2 *texture = new SoTexture2;
  texture->filename.setValue ("nutture.rgb");
  gameRoot->addChild (texture);

  horShift = new SoTransform;
  gameRoot->addChild (horShift);

  for (m=0; m<MAX_M; m++)
    for (n=0; n<MAX_N; n++)
      {
       group[m][n] = new SoSeparator;
       sphere[m][n] = new SoSphere;
       material[m][n] = new SoMaterial;
       transform[m][n] = new SoTransform;

       gameRoot->addChild (group[m][n]);
       group[m][n]->addChild (transform[m][n]);
       group[m][n]->addChild (material[m][n]);
       group[m][n]->addChild (sphere[m][n]);

       transform[m][n]->translation.setValue (m*SHIFT, n*SHIFT, 0);
       sphere[m][n]->radius.setValue (0);

       sprintf (name, "_%d_%d", m, n);
       sphere[m][n]->setName (name);
           
       material[m][n]->diffuseColor.setValue (.9, .8, 0);
      }

  material[0][0]->diffuseColor.setValue (0, .8, .9);
}

void playGame (void)
{
  int m, n;

  for (m=0; m<M; m++)
    for (n=0; n<N; n++)
      sphere[m][n]->radius.setValue (RADIUS);
}

void setup_sCB (void *, SoPath *selectionPath)
{
  SoCone *ourCone;
  char name[8];

  if (selectionPath->getTail ()->
    isOfType (SoCube::getClassTypeId ()))
      {
       start_rot_sens->unschedule();
//       startRoot->unref ();
       turn->string.setValue ("Player 1 Up");
       turn->setName ("Player_1_Up");
       playGame ();
       allShift->translation.setValue (0, (MAX_N-N)*SHIFT/2, 0);
       horShift->translation.setValue (-((M-1)*SHIFT+RADIUS)/2, 0, 0);
       viewer->setSceneGraph (gameRoot);
      }
  else if (selectionPath->getTail ()->
    isOfType (SoCone::getClassTypeId ()))
      {
       ourCone = (SoCone*) selectionPath->getTail ();
       strcpy (name, ourCone->getName ().getString ());

       if (strcmp (name, "HorUp") == 0)
         {
          M++;
          if (M > MAX_M) M=MAX_M;
          horVal->string = M;
         }
       else if (strcmp (name, "HorDown") == 0)
         {
          M--;
          if (M == 1) M=2;
          horVal->string = M;
         }
       else if (strcmp (name, "VerUp") == 0)
         {
          N++;
          if (N > MAX_N) N=MAX_N;
          verVal->string = N;
         }
       else
         {
          N--;
          if (N==1) N=2;
          verVal->string = N;
         }
      }

  setupRoot->deselect (selectionPath->getTail ());
}

void make_setupRoot (void)
{
  setupRoot = new SoSelection;
  setupRoot->ref ();
  setupRoot->addSelectionCallback (setup_sCB);

  SoPerspectiveCamera *camera = new SoPerspectiveCamera;
  camera->position.setValue (-.08, -34.29, 250);
  setupRoot->addChild (camera);
  setupRoot->addChild (new SoDirectionalLight);

  SoSeparator *title = new SoSeparator;
  setupRoot->addChild (title);

  SoFont *titleFont = new SoFont;
  titleFont->name.setValue ("Times-Roman");
  titleFont->size.setValue (40);
  title->addChild (titleFont);

  SoTransform *titleTrans = new SoTransform;
  titleTrans->translation.setValue (0, 30, 0);
  titleTrans->rotation.setValue (SbVec3f (1, 0, 0), -M_PI/6);
  title->addChild (titleTrans);

  SoTexture2 *titleTexture = new SoTexture2;
  titleTexture->filename.setValue ("nutture.rgb");
  title->addChild (titleTexture);

  SoText3 *titleText = new SoText3;
  titleText->parts = SoText3::ALL;
  titleText->justification.setValue (SoText3::CENTER);
  titleText->string.setValue ("Peanuts!");
  title->addChild (titleText);

  SoSeparator *instr = new SoSeparator;
  setupRoot->addChild (instr);

  SoFont *instrFont = new SoFont;
  instrFont->name.setValue ("Times-Roman");
  instrFont->size.setValue (10);
  instr->addChild (instrFont);

  SoText3 *instrText = new SoText3;
  instrText->parts = SoText3::FRONT;
  instrText->justification.setValue (SoText3::CENTER);
  instrText->string.set1Value (0, "``Peanuts!'' is a game of strategy and skill.");
  instrText->string.set1Value (1, "It is a two-player game, in which players sequentially");
  instrText->string.set1Value (2, "eat peanuts.  When a peanut is selected, all the peanuts");
  instrText->string.set1Value (3, "above and to the right of it in the array disappear.");
  instrText->string.set1Value (4, "Whoever eats the rotten peanut in the lower left");
  instrText->string.set1Value (5, "corner, loses.  Good luck!");
  instr->addChild (instrText);

  SoSeparator *ok = new SoSeparator;
  setupRoot->addChild (ok);

  SoTransform *okTrans = new SoTransform;
  okTrans->translation.setValue (0, -100, 0);
  ok->addChild (okTrans);

  SoTexture2 *okTexture = new SoTexture2;
  okTexture->filename.setValue ("mrpnut.rgb");
  ok->addChild (okTexture);

  SoCube *okBar = new SoCube;
  okBar->width.setValue (30);
  okBar->height.setValue (45);  
  okBar->depth.setValue (2);
  ok->addChild (okBar);

  SoSeparator *under = new SoSeparator;
  setupRoot->addChild (under);

  SoFont *underFont = new SoFont;
  underFont->name.setValue ("Times-Roman");
  underFont->size.setValue (5);
  under->addChild (underFont);

  SoSeparator *left = new SoSeparator;
  under->addChild (left);

  SoTransform *leftTransform = new SoTransform;
  leftTransform->translation.setValue (-70, -110, 0);
  left->addChild (leftTransform);

  SoText3 *leftText = new SoText3;
  leftText->parts = SoText3::ALL;
  leftText->string.setValue ("Horizontal Size of the Array");
  leftText->justification.setValue (SoText3::CENTER);
  left->addChild (leftText);

  SoSeparator *right = new SoSeparator;
  under->addChild (right);

  SoTransform *rightTransform = new SoTransform;
  rightTransform->translation.setValue (70, -110, 0);
  right->addChild (rightTransform);

  SoText3 *rightText = new SoText3;
  rightText->parts = SoText3::ALL;
  rightText->string.setValue ("Vertical Size of the Array");
  rightText->justification.setValue (SoText3::CENTER);
  right->addChild (rightText);

  SoSeparator *values = new SoSeparator;
  setupRoot->addChild (values);

  SoFont *valueFont = new SoFont;
  valueFont->name.setValue ("Times-Roman");
  valueFont->size.setValue (25);
  values->addChild (valueFont);  

  SoSeparator *hor = new SoSeparator;
  values->addChild (hor);

  SoTransform *horTrans = new SoTransform;
  horTrans->translation.setValue (-65, -90, 0);
  horTrans->rotation.setValue (SbVec3f (0, 1, 0), M_PI/3);
  hor->addChild (horTrans);

  horVal = new SoText3;
  horVal->parts = SoText3::ALL;
  horVal->justification.setValue (SoText3::CENTER);
  horVal->string = M;
  hor->addChild (horVal);

  SoSeparator *ver = new SoSeparator;
  values->addChild (ver);

  SoTransform *verTrans = new SoTransform;
  verTrans->translation.setValue (65, -90, 0);
  verTrans->rotation.setValue (SbVec3f (0, 1, 0), -M_PI/3);
  ver->addChild (verTrans);

  verVal = new SoText3;
  verVal->parts = SoText3::ALL;
  verVal->justification.setValue (SoText3::CENTER);
  verVal->string = N;
  ver->addChild (verVal);

  SoSeparator *horUp = new SoSeparator;
  setupRoot->addChild (horUp);

  SoMaterial *horUpMat = new SoMaterial;
  horUpMat->diffuseColor.setValue (.7, .9, 0);
  horUp->addChild (horUpMat);

  SoTransform *horUpTrans = new SoTransform;
  horUpTrans->translation.setValue (-50, -77, 0);
  horUp->addChild (horUpTrans);

  SoCone *horUpCone = new SoCone;
  horUpCone->setName ("HorUp");
  horUpCone->bottomRadius.setValue (3);
  horUpCone->height.setValue (6);
  horUp->addChild (horUpCone);

  SoSeparator *horDown = new SoSeparator;
  setupRoot->addChild (horDown);

  SoMaterial *horDownMat = new SoMaterial;
  horDownMat->diffuseColor.setValue (.9, .7, 0);
  horDown->addChild (horDownMat);

  SoTransform *horDownTrans = new SoTransform;
  horDownTrans->translation.setValue (-50, -87, 0);
  horDownTrans->rotation.setValue (SbVec3f (1, 0, 0), M_PI);
  horDown->addChild (horDownTrans);

  SoCone *horDownCone = new SoCone;
  horDownCone->setName ("HorDown");
  horDownCone->bottomRadius.setValue (3);
  horDownCone->height.setValue (6);
  horDown->addChild (horDownCone);

  SoSeparator *verUp = new SoSeparator;
  setupRoot->addChild (verUp);

  SoMaterial *verUpMat = new SoMaterial;
  verUpMat->diffuseColor.setValue (.7, .9, 0);
  verUp->addChild (verUpMat);

  SoTransform *verUpTrans = new SoTransform;
  verUpTrans->translation.setValue (50, -77, 0);
  verUp->addChild (verUpTrans);

  SoCone *verUpCone = new SoCone;
  verUpCone->setName ("VerUp");
  verUpCone->bottomRadius.setValue (3);
  verUpCone->height.setValue (6);
  verUp->addChild (verUpCone);

  SoSeparator *verDown = new SoSeparator;
  setupRoot->addChild (verDown);

  SoMaterial *verDownMat = new SoMaterial;
  verDownMat->diffuseColor.setValue (.9, .7, 0);
  verDown->addChild (verDownMat);

  SoTransform *verDownTrans = new SoTransform;
  verDownTrans->translation.setValue (50, -87, 0);
  verDownTrans->rotation.setValue (SbVec3f (1, 0, 0), M_PI);
  verDown->addChild (verDownTrans);

  SoCone *verDownCone = new SoCone;
  verDownCone->setName ("VerDown");
  verDownCone->bottomRadius.setValue (3);
  verDownCone->height.setValue (6);
  verDown->addChild (verDownCone);
}

void main (int, char **argv)
{
  Widget window = SoXt::init (argv[0]);
  if (window == NULL) exit (1);
  viewer = new SoXtExaminerViewer 
    (window, NULL, TRUE, SoXtExaminerViewer::BUILD_NONE);

  make_startRoot ();
  make_setupRoot ();
  make_gameRoot ();
  make_quitRoot ();

  viewer->setViewing (FALSE);
  viewer->setSize (SbVec2s (1200, 900));
  viewer->setTitle ("Peanuts!");
  viewer->setSceneGraph (startRoot);
  viewer->show ();

  SoXt::show (window);
  SoXt::mainLoop ();
}
That's all, folks!

We hope you enjoyed taking this course; we certainly enjoyed teaching it. Again, please feel free to send us email with any comments you have.

Back to the CGW '96 home page

$Id: index.html,v 1.5 1996/02/04 22:41:02 kbrussel Exp $