'From Squeak3.9 of 21 July 2007 [latest update: #7068] on 24 July 2007 at 9:15:33 pm'! TestCase subclass: #BlankCellTestCase instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Tests'! Object subclass: #Cell instanceVariableNames: 'activeSegments exitSides gridLocation' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! Cell subclass: #BlankCell instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! Object subclass: #CellRenderer instanceVariableNames: 'cellLocation grid targetForm' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Graphics'! CellRenderer subclass: #BlankCellRenderer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Graphics'! TestCase subclass: #CellRendererTestCase instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Tests'! Object subclass: #Grid instanceVariableNames: 'cells laserIsActive numberOfColumns numberOfRows laserBeamPath' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! Object subclass: #GridDirection instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! GridDirection subclass: #GridDirectionEast instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! GridDirection subclass: #GridDirectionNorth instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! GridDirection subclass: #GridDirectionSouth instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! TestCase subclass: #GridDirectionTestCase instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Tests'! GridDirection subclass: #GridDirectionWest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! Object subclass: #GridFactory instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! TestCase subclass: #GridTestCase instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Tests'! Morph subclass: #LaserGame instanceVariableNames: 'grid boardForm' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Graphics'! Object subclass: #LaserGameColors instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Graphics'! Object subclass: #LaserPathElement instanceVariableNames: 'cell entrySide' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! Cell subclass: #MirrorCell instanceVariableNames: 'leansLeft' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! CellRenderer subclass: #MirrorCellRenderer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Graphics'! TestCase subclass: #MirrorCellTestCase instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Tests'! Cell subclass: #TargetCell instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Model'! CellRenderer subclass: #TargetCellRenderer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Graphics'! TestCase subclass: #TargetCellTestCase instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Laser-Game-Tests'! !Object methodsFor: '*Laser-Game-Model' stamp: 'sbw 7/24/2007 17:19'! revisit: aString "Does nothing."! ! !BlankCellTestCase methodsFor: 'tests' stamp: 'sbw 7/22/2007 23:44'! testCellExitSides | cell exit | cell := BlankCell new. exit := cell exitSideFor: #north. self should: [exit = #south]. exit := cell exitSideFor: #east. self should: [exit = #west]. exit := cell exitSideFor: #south. self should: [exit = #north]. exit := cell exitSideFor: #west. self should: [exit = #east].! ! !BlankCellTestCase methodsFor: 'tests' stamp: 'sbw 7/22/2007 23:47'! testCellLaserActivity | cell | cell := BlankCell new. cell laserEntersFrom: #north. self should: [cell isOn]. self should: [cell isSegmentOnFor: #north]. self should: [cell isSegmentOnFor: #south]. self shouldnt: [cell isSegmentOnFor: #east]. self shouldnt: [cell isSegmentOnFor: #west]. ! ! !BlankCellTestCase methodsFor: 'tests' stamp: 'sbw 7/22/2007 08:44'! testCellOnState | cell | cell := BlankCell new. self should: [cell isOff]. self shouldnt: [cell isOn]. ! ! !BlankCellTestCase methodsFor: 'tests' stamp: 'sbw 7/22/2007 08:57'! testCellSegmentsState | cell | cell := BlankCell new. self shouldnt: [cell isSegmentOnFor: #north]. self shouldnt: [cell isSegmentOnFor: #east]. self shouldnt: [cell isSegmentOnFor: #south]. self shouldnt: [cell isSegmentOnFor: #west]. ! ! !Cell methodsFor: 'initialize-release' stamp: 'sbw 7/22/2007 23:57'! initialize super initialize. self initializeActiveSegments. ! ! !Cell methodsFor: 'initialize-release' stamp: 'sbw 7/22/2007 23:57'! initializeActiveSegments self activeSegments: Dictionary new. self activeSegments at: #north put: false. self activeSegments at: #east put: false. self activeSegments at: #south put: false. self activeSegments at: #west put: false. ! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/22/2007 23:54'! activeSegments "Answer the value of activeSegments" ^ activeSegments! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/22/2007 23:55'! activeSegments: anObject "Set the value of activeSegments" activeSegments := anObject! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/24/2007 21:09'! clearCell self initializeActiveSegments! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/23/2007 00:02'! exitSideFor: aSymbol ^self exitSides at: aSymbol! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/22/2007 23:55'! exitSides "Answer the value of exitSides" ^ exitSides! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/22/2007 23:55'! exitSides: anObject "Set the value of exitSides" exitSides := anObject! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:33'! gridLocation "Answer the value of gridLocation" ^ gridLocation! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:33'! gridLocation: anObject "Set the value of gridLocation" gridLocation := anObject! ! !Cell methodsFor: 'accessing' stamp: 'sbw 7/23/2007 00:05'! laserEntersFrom: aSymbol | exit | self activeSegments at: aSymbol put: true. exit := self exitSideFor: aSymbol. self activeSegments at: exit put: true. ! ! !Cell methodsFor: 'testing' stamp: 'sbw 7/23/2007 00:03'! isOff ^self isOn not! ! !Cell methodsFor: 'testing' stamp: 'sbw 7/23/2007 00:03'! isOn ^self activeSegments values anySatisfy: [:each | each = true]! ! !Cell methodsFor: 'testing' stamp: 'sbw 7/23/2007 00:05'! isSegmentOnFor: aSymbol ^self activeSegments at: aSymbol! ! !BlankCell methodsFor: 'initialize-release' stamp: 'sbw 7/22/2007 23:57'! initialize super initialize. self initializeExitSides. ! ! !BlankCell methodsFor: 'initialize-release' stamp: 'sbw 7/22/2007 23:40'! initializeExitSides self exitSides: Dictionary new. self exitSides at: #north put: #south. self exitSides at: #east put: #west. self exitSides at: #south put: #north. self exitSides at: #west put: #east. ! ! !CellRenderer methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:38'! cellLocation "Answer the value of cellLocation" ^ cellLocation! ! !CellRenderer methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:38'! cellLocation: anObject "Set the value of cellLocation" cellLocation := anObject! ! !CellRenderer methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:38'! grid "Answer the value of grid" ^ grid! ! !CellRenderer methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:38'! grid: anObject "Set the value of grid" grid := anObject! ! !CellRenderer methodsFor: 'accessing' stamp: 'sbw 7/24/2007 19:01'! offsetWithinGridForm | delta xCount yCount offset | delta := CellRenderer cellExtent. xCount := (self cellLocation x) - 1. yCount := (self cellLocation y) - 1. offset := delta * (xCount@yCount). ^offset! ! !CellRenderer methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:38'! targetForm "Answer the value of targetForm" ^ targetForm! ! !CellRenderer methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:38'! targetForm: anObject "Set the value of targetForm" targetForm := anObject! ! !CellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 18:48'! render self renderBorder; renderContents! ! !CellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:13'! renderBorder self renderBorderTop; renderBorderRight; renderBorderBottom; renderBorderLeft! ! !CellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:27'! renderBorderBottom | delta offset x1 x2 y1 y2 line fillForm | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. fillForm := Form extent: 1@1 depth: 8. fillForm fillColor: LaserGameColors cellBorderColor. line := Line from: x1@y1 to: x2@y2 withForm: fillForm. line displayOn: self targetForm. ! ! !CellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:28'! renderBorderLeft | delta offset x1 x2 y1 y2 line fillForm | delta := CellRenderer cellExtent. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1. y1 := offset y. y2 := y1 + delta y. fillForm := Form extent: 1@1 depth: 8. fillForm fillColor: LaserGameColors cellBorderColor. line := Line from: x1@y1 to: x2@y2 withForm: fillForm. line displayOn: self targetForm. ! ! !CellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:27'! renderBorderRight | delta offset x1 x2 y1 y2 line fillForm | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x + delta x. x2 := x1. y1 := offset y. y2 := y1 + delta y. fillForm := Form extent: 1@1 depth: 8. fillForm fillColor: LaserGameColors cellBorderColor. line := Line from: x1@y1 to: x2@y2 withForm: fillForm. line displayOn: self targetForm. ! ! !CellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:27'! renderBorderTop | delta offset x1 x2 y1 y2 line fillForm | delta := CellRenderer cellExtent. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y. y2 := y1. fillForm := Form extent: 1@1 depth: 8. fillForm fillColor: LaserGameColors cellBorderColor. line := Line from: x1@y1 to: x2@y2 withForm: fillForm. line displayOn: self targetForm. ! ! !CellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:52'! renderContents! ! !CellRenderer class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:49'! cellExtent ^30@30! ! !CellRenderer class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:41'! rendererFor: aCell ^self subclasses detect: [:cls | cls modelClass = aCell class]! ! !CellRenderer class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 19:03'! rendererFor: aCell grid: aGrid form: aForm | cls model | cls := self rendererFor: aCell. model := cls new. model cellLocation: aCell gridLocation; grid: aGrid; targetForm: aForm. ^model! ! !BlankCellRenderer class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:40'! modelClass ^BlankCell! ! !CellRendererTestCase methodsFor: 'tests' stamp: 'sbw 7/24/2007 19:06'! testCellOffsetCalculations | grid form cellLoc cell renderer offset | grid := GridFactory demoGrid. form := Form extent: (LaserGame boardExtentFor: grid) depth: Display depth. form fillColor: (Color r: 0.820 g: 0.820 b: 0.820). cellLoc := 1@1. cell := grid at: cellLoc. renderer := CellRenderer rendererFor: cell grid: grid form: form. offset := renderer offsetWithinGridForm. self should: [offset = (0@0)]. cellLoc := 2@1. cell := grid at: cellLoc. renderer := CellRenderer rendererFor: cell grid: grid form: form. offset := renderer offsetWithinGridForm. self should: [offset = (30@0)]. cellLoc := 1@2. cell := grid at: cellLoc. renderer := CellRenderer rendererFor: cell grid: grid form: form. offset := renderer offsetWithinGridForm. self should: [offset = (0@30)]. cellLoc := 2@2. cell := grid at: cellLoc. renderer := CellRenderer rendererFor: cell grid: grid form: form. offset := renderer offsetWithinGridForm. self should: [offset = (30@30)]. ! ! !CellRendererTestCase methodsFor: 'tests' stamp: 'sbw 7/24/2007 18:43'! testRenderSelection | renderer cell | cell := BlankCell new. renderer := CellRenderer rendererFor: cell. self should: [renderer = BlankCellRenderer]. cell := MirrorCell new. renderer := CellRenderer rendererFor: cell. self should: [renderer = MirrorCellRenderer]. cell := TargetCell new. renderer := CellRenderer rendererFor: cell. self should: [renderer = TargetCellRenderer]. ! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:01'! activateCellsInPath self calculatePath. self laserBeamPath do: [:pe | pe activateCell]! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:56'! at: aPoint self revisit: 'sbw 05/21/2007 - We should add a more meaningful accessing technique here. x@y is confusing.'. ^self cells at: aPoint ifAbsent: []! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:34'! at: aPoint put: aCell self revisit: 'sbw 05/21/2007 - We should add a more meaningful accessing technique here. x@y is confusing.'. aCell gridLocation: aPoint. self cells at: aPoint put: aCell! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:00'! calculatePath | cell dirSym element next | self laserBeamPath: OrderedCollection new. cell := self startingCell. dirSym := #south. element := LaserPathElement cell: cell entrySide: dirSym. [self laserBeamPath addLast: element. next := element nextElementIn: self. next isNil] whileFalse: [ element := next]! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/23/2007 06:45'! cells "Answer the value of cells" ^ cells! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/23/2007 06:45'! cells: anObject "Set the value of cells" cells := anObject! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:30'! laserBeamPath "Answer the value of laserBeamPath" ^ laserBeamPath! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:30'! laserBeamPath: anObject "Set the value of laserBeamPath" laserBeamPath := anObject! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/23/2007 06:45'! laserIsActive "Answer the value of laserIsActive" ^ laserIsActive! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/23/2007 06:45'! laserIsActive: anObject "Set the value of laserIsActive" laserIsActive := anObject! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/23/2007 06:49'! numberOfColumns numberOfColumns isNil ifTrue: [self numberOfColumns: 1]. ^ numberOfColumns! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/23/2007 06:46'! numberOfColumns: anObject "Set the value of numberOfColumns" numberOfColumns := anObject! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/23/2007 06:49'! numberOfRows numberOfRows isNil ifTrue: [self numberOfRows: 1]. ^ numberOfRows! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/23/2007 06:46'! numberOfRows: anObject "Set the value of numberOfRows" numberOfRows := anObject! ! !Grid methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:31'! startingCell | pt | pt := 1@(self numberOfRows). ^self at: pt! ! !Grid methodsFor: 'initialize-release' stamp: 'sbw 7/23/2007 06:47'! initialize super initialize. self laserIsActive: false. self initializeCells. ! ! !Grid methodsFor: 'initialize-release' stamp: 'sbw 7/24/2007 18:21'! initializeCells self cells: Dictionary new. 1 to: self numberOfColumns do: [:x | 1 to: self numberOfRows do: [:y | | pt cell | pt := x@y. cell := BlankCell new. self at: pt put: cell]]! ! !Grid methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 21:10'! clearCellsInPath self calculatePath. self laserBeamPath do: [:pe | pe clearCell]! ! !Grid methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 20:56'! fireLaser self laserIsActive: true. self activateCellsInPath! ! !Grid methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 20:57'! stopLaser self laserIsActive: false. self clearCellsInPath! ! !Grid class methodsFor: 'instance creation' stamp: 'sbw 7/23/2007 07:01'! newOfSize: aPoint | model | model := self basicNew. model numberOfRows: aPoint y; numberOfColumns: aPoint x. model initialize. ^model! ! !GridDirection class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:43'! directionFor: aSymbol ^self subclasses detect: [:cls | cls directionSymbol = aSymbol]! ! !GridDirectionEast class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:26'! adjacentInversionSymbol ^#west! ! !GridDirectionEast class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:39'! directionSymbol ^#east! ! !GridDirectionEast class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:40'! vector ^1@0! ! !GridDirectionNorth class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:26'! adjacentInversionSymbol ^#south! ! !GridDirectionNorth class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:39'! directionSymbol ^#north! ! !GridDirectionNorth class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:39'! vector ^0@-1! ! !GridDirectionSouth class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:26'! adjacentInversionSymbol ^#north! ! !GridDirectionSouth class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:41'! directionSymbol ^#south! ! !GridDirectionSouth class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:41'! vector ^0@1! ! !GridDirectionTestCase methodsFor: 'tests' stamp: 'sbw 7/24/2007 18:31'! testDirectionSelection | direction | direction := GridDirection directionFor: #north. self should: [direction = GridDirectionNorth]. self should: [direction vector = (0@-1)]. self should: [direction adjacentInversionSymbol = #south]. direction := GridDirection directionFor: #east. self should: [direction = GridDirectionEast]. self should: [direction vector = (1@0)]. self should: [direction adjacentInversionSymbol = #west]. direction := GridDirection directionFor: #south. self should: [direction = GridDirectionSouth]. self should: [direction vector = (0@1)]. self should: [direction adjacentInversionSymbol = #north]. direction := GridDirection directionFor: #west. self should: [direction = GridDirectionWest]. self should: [direction vector = (-1@0)]. self should: [direction adjacentInversionSymbol = #east]. ! ! !GridDirectionWest class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:27'! adjacentInversionSymbol ^#east! ! !GridDirectionWest class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:42'! directionSymbol ^#west! ! !GridDirectionWest class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:42'! vector ^-1@0! ! !GridFactory class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:55'! demoGrid | grid | grid := Grid newOfSize: 5@5. grid at: 4@1 put: MirrorCell leanRight. grid at: 5@1 put: TargetCell new. grid at: 1@2 put: MirrorCell leanRight. grid at: 5@2 put: MirrorCell leanLeft. grid at: 2@3 put: MirrorCell leanLeft. grid at: 3@3 put: MirrorCell leanRight. grid at: 5@3 put: MirrorCell leanLeft. grid at: 2@4 put: MirrorCell leanLeft. grid at: 3@4 put: MirrorCell leanLeft. grid at: 1@5 put: MirrorCell leanRight. grid at: 4@5 put: MirrorCell leanRight. ^grid! ! !GridTestCase methodsFor: 'private' stamp: 'sbw 7/24/2007 18:56'! generateDemoGrid ^GridFactory demoGrid! ! !GridTestCase methodsFor: 'tests' stamp: 'sbw 7/24/2007 18:35'! testCellInteractions | grid cell expecetdActiveLocationsList foundOn | grid := self generateDemoGrid. cell := grid at: 5@1. self should: [cell isOff]. grid activateCellsInPath. self should: [cell isOn]. expecetdActiveLocationsList := { 1@5. 2@5. 3@5. 4@5. 4@4. 4@3. 4@2. 4@1. 5@1 }. foundOn := grid cells select: [:each | each isOn]. self should: [foundOn size = expecetdActiveLocationsList size]. foundOn do: [:fCell | self should: [expecetdActiveLocationsList includes: fCell gridLocation]]! ! !GridTestCase methodsFor: 'tests' stamp: 'sbw 7/24/2007 21:05'! testFireLaser | grid cell | grid := self generateDemoGrid. grid fireLaser. self should: [grid laserIsActive]. cell := grid startingCell. self should: [cell isOn]. cell := grid at: 5@1. self should: [cell isOn]! ! !GridTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:53'! testInitialConditions | grid cell | grid := Grid new. self shouldnt: [grid laserIsActive]. cell := grid at: 1@1. self should: [cell class = BlankCell]. ! ! !GridTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 07:03'! testNonDefaultGridSizeConditions | grid cell | grid := Grid newOfSize: 4@4.. self shouldnt: [grid laserIsActive]. cell := grid at: 1@1. self should: [cell class = BlankCell]. cell := grid at: 2@3. self should: [cell class = BlankCell]. self should: [cell isOff]. ! ! !GridTestCase methodsFor: 'tests' stamp: 'sbw 7/24/2007 21:06'! testStopLaser | grid cell | grid := self generateDemoGrid. grid stopLaser. self shouldnt: [grid laserIsActive]. cell := grid startingCell. self should: [cell isOff]. cell := grid at: 5@1. self should: [cell isOff].! ! !GridTestCase methodsFor: 'tests' stamp: 'sbw 7/24/2007 21:07'! testToggleLaser | grid cell | grid := self generateDemoGrid. grid fireLaser. grid stopLaser. self shouldnt: [grid laserIsActive]. cell := grid startingCell. self should: [cell isOff]. cell := grid at: 5@1. self should: [cell isOff].! ! !LaserGame methodsFor: 'accessing' stamp: 'sbw 7/24/2007 19:55'! boardForm "Answer the value of boardForm" ^ boardForm! ! !LaserGame methodsFor: 'accessing' stamp: 'sbw 7/24/2007 19:55'! boardForm: anObject "Set the value of boardForm" boardForm := anObject! ! !LaserGame methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:51'! grid "Answer the value of grid" ^ grid! ! !LaserGame methodsFor: 'accessing' stamp: 'sbw 7/24/2007 18:51'! grid: anObject "Set the value of grid" grid := anObject! ! !LaserGame methodsFor: 'constants' stamp: 'sbw 7/24/2007 19:59'! calculatedExtent | pt | pt := self boardForm extent. pt := pt + (self panelWidth@0). ^pt! ! !LaserGame methodsFor: 'constants' stamp: 'sbw 7/24/2007 19:58'! panelWidth ^100! ! !LaserGame methodsFor: 'constants' stamp: 'sbw 7/24/2007 19:59'! setExtent self extent: self calculatedExtent! ! !LaserGame methodsFor: 'drawing' stamp: 'sbw 7/24/2007 20:11'! drawGameBoard | cell renderer | 1 to: self grid numberOfColumns do: [:x | 1 to: self grid numberOfRows do: [:y | cell := self grid at: x@y. renderer := CellRenderer rendererFor: cell grid: self grid form: self boardForm. renderer render]].! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 21:02'! findFireButton ^self allMorphs detect: [:m | m knownName = 'fireButton'] ifNone: []! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:59'! fireButtonLabel ^self laserActive ifTrue: ['Stop'] ifFalse: ['Fire']! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 21:04'! fireLaser self laserActive ifTrue: [self grid stopLaser] ifFalse: [self grid fireLaser]. self drawGameBoard. self changed. self updateFireButtonLabel! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:11'! initialize super initialize. self grid: GridFactory demoGrid. self boardForm: (Form extent: (self class boardExtentFor: self grid) depth: Display depth). self boardForm fillColor: LaserGameColors gameBoardBackgroundColor. self setExtent. self setupMorphs. self drawGameBoard. ! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:58'! laserActive ^self grid laserIsActive! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:29'! makeButton: label action: actionSymbol state: stateSymbol | btn labelMorph | btn := PluggableButtonMorph on: self getState: stateSymbol action: actionSymbol. labelMorph := StringMorph contents: label. labelMorph emphasis: 1. btn label: labelMorph; useRoundedCorners; hResizing: #spaceFill; onColor: Color veryLightGray offColor: Color lightGray; borderWidth: 2; borderColor: #raised. btn label color: Color darkGray. ^btn! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:47'! makeControlPanelMorph | panel buttonHeight vertOffsetTop vertOffsetBtm | panel := RectangleMorph new borderWidth: 0; color: Color white; layoutPolicy: ProportionalLayout new. buttonHeight := 26. vertOffsetTop := 10 + buttonHeight + 10 + buttonHeight. vertOffsetBtm := 10 + buttonHeight + 10. panel addMorph: self makeFireLaserButton fullFrame: (LayoutFrame fractions: (0@1 corner: 1@1) offsets: ( (20 @ (vertOffsetTop negated)) corner: (-20 @ (vertOffsetBtm negated)))). vertOffsetTop := 10 + buttonHeight. vertOffsetBtm := 10. panel addMorph: self makeQuitGameButton fullFrame: (LayoutFrame fractions: (0@1 corner: 1@1) offsets: ( (20 @ (vertOffsetTop negated)) corner: (-20 @ (vertOffsetBtm negated)))). ^panel! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 21:02'! makeFireLaserButton | btn | btn := self makeButton: self fireButtonLabel action: #fireLaser state: #laserActive. btn name: 'fireButton'. ^btn! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:06'! makeGameBoardMorph | boardMorph | boardMorph := SketchMorph withForm: self boardForm. ^boardMorph! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:30'! makeQuitGameButton ^self makeButton: 'Quit' action: #quitGame state: nil! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:48'! quitGame self delete! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 20:03'! setupMorphs self layoutPolicy: ProportionalLayout new. self addMorph: self makeGameBoardMorph fullFrame: (LayoutFrame fractions: (0@0 corner: 1@1) offsets: (0@0 corner: self panelWidth negated @ 0)). self addMorph: self makeControlPanelMorph fullFrame: (LayoutFrame fractions: (1@0 corner: 1@1) offsets: (self panelWidth negated @ 0 corner: 0@0)).! ! !LaserGame methodsFor: 'initialization' stamp: 'sbw 7/24/2007 21:03'! updateFireButtonLabel | btn | btn := self findFireButton. btn notNil ifTrue: [btn label contents: self fireButtonLabel]! ! !LaserGame class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:52'! boardExtentFor: aGrid | x y | x := CellRenderer cellExtent x * aGrid numberOfColumns. y := CellRenderer cellExtent y * aGrid numberOfRows. ^x@y! ! !LaserGameColors class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 19:25'! cellBorderColor ^Color darkGray! ! !LaserGameColors class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 19:25'! gameBoardBackgroundColor ^Color r: 0.860 g: 0.860 b: 0.860! ! !LaserGameColors class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 19:25'! mirrorColor ^Color blue! ! !LaserGameColors class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 19:46'! targetCenterColor ^Color r: 0.0 g: 0.0 b: 0.92! ! !LaserGameColors class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 19:47'! targetCenterColorActive ^Color r: 1.0 g: 1.0 b: 0.634! ! !LaserGameColors class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 19:46'! targetCenterColorIdle ^Color r: 0.313 g: 0.753 b: 0.976! ! !LaserPathElement methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:29'! cell "Answer the value of cell" ^ cell! ! !LaserPathElement methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:29'! cell: anObject "Set the value of cell" cell := anObject! ! !LaserPathElement methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:29'! entrySide "Answer the value of entrySide" ^ entrySide! ! !LaserPathElement methodsFor: 'accessing' stamp: 'sbw 7/24/2007 17:29'! entrySide: anObject "Set the value of entrySide" entrySide := anObject! ! !LaserPathElement methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:02'! activateCell self cell laserEntersFrom: self entrySide! ! !LaserPathElement methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 21:09'! clearCell self cell clearCell! ! !LaserPathElement methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:29'! nextElementIn: aGrid | loc dirSym direction vector newLoc nextCell | loc := self cell gridLocation. dirSym := self cell exitSideFor: self entrySide. dirSym isNil ifTrue: [^nil]. direction := GridDirection directionFor: dirSym. vector := direction vector. newLoc := loc + vector. nextCell := aGrid at: newLoc. ^nextCell isNil ifTrue: [nil] ifFalse: [self class cell: nextCell entrySide: direction adjacentInversionSymbol]! ! !LaserPathElement class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 17:52'! cell: aCell entrySide: aSymbol | model | model := self basicNew. model cell: aCell; entrySide: aSymbol. model initialize. ^model! ! !MirrorCell methodsFor: 'accessing' stamp: 'sbw 7/22/2007 23:59'! leanLeft self leansLeft: true. self exitSides at: #north put: #east. self exitSides at: #east put: #north. self exitSides at: #south put: #west. self exitSides at: #west put: #south. ! ! !MirrorCell methodsFor: 'accessing' stamp: 'sbw 7/22/2007 23:59'! leanRight self leansLeft: false. self exitSides at: #north put: #west. self exitSides at: #east put: #south. self exitSides at: #south put: #east. self exitSides at: #west put: #north. ! ! !MirrorCell methodsFor: 'accessing' stamp: 'sbw 7/22/2007 23:49'! leansLeft "Answer the value of leansLeft" ^ leansLeft! ! !MirrorCell methodsFor: 'accessing' stamp: 'sbw 7/22/2007 23:49'! leansLeft: anObject "Set the value of leansLeft" leansLeft := anObject! ! !MirrorCell methodsFor: 'testing' stamp: 'sbw 7/22/2007 23:51'! isLeft ^self leansLeft! ! !MirrorCell methodsFor: 'testing' stamp: 'sbw 7/22/2007 23:52'! isRight ^self isLeft not! ! !MirrorCell methodsFor: 'initialize-release' stamp: 'sbw 7/23/2007 00:01'! initialize super initialize. self initializeExitSides. self leanLeft! ! !MirrorCell methodsFor: 'initialize-release' stamp: 'sbw 7/23/2007 00:00'! initializeExitSides self exitSides: Dictionary new. ! ! !MirrorCell class methodsFor: 'instance creation' stamp: 'sbw 7/23/2007 06:32'! leanLeft ^super new leanLeft! ! !MirrorCell class methodsFor: 'instance creation' stamp: 'sbw 7/23/2007 06:32'! leanRight ^super new leanRight! ! !MirrorCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:17'! cornerInset ^8@8! ! !MirrorCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:17'! renderContents | cell | cell := self grid at: self cellLocation. cell isLeft ifTrue: [self renderContentsLeanLeft] ifFalse: [self renderContentsLeanRight]! ! !MirrorCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:29'! renderContentsLeanLeft | offset delta x1 x2 y1 y2 line fillForm | offset := self offsetWithinGridForm. delta := CellRenderer cellExtent - 1. x1 := offset x + (self cornerInset x). x2 := offset x + delta x - (self cornerInset x). y1 := offset y + (self cornerInset y). y2 := offset y + delta y - (self cornerInset y). fillForm := Form extent: 2@2 depth: 8. fillForm fillColor: LaserGameColors mirrorColor. line := Line from: x1@y1 to: x2@y2 withForm: fillForm. line displayOn: self targetForm! ! !MirrorCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:29'! renderContentsLeanRight | offset delta x1 x2 y1 y2 line fillForm | offset := self offsetWithinGridForm. delta := CellRenderer cellExtent - 1. x1 := offset x + delta x - self cornerInset x. x2 := offset x + self cornerInset x. y1 := offset y + (self cornerInset y). y2 := offset y + delta y - (self cornerInset y). fillForm := Form extent: 2@2 depth: 8. fillForm fillColor: LaserGameColors mirrorColor. line := Line from: x1@y1 to: x2@y2 withForm: fillForm. line displayOn: self targetForm! ! !MirrorCellRenderer class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:40'! modelClass ^MirrorCell! ! !MirrorCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:27'! testCellExitSidesMirrorLeft | cell exit | cell := MirrorCell new. cell leanLeft. exit := cell exitSideFor: #north. self should: [exit = #east]. exit := cell exitSideFor: #east. self should: [exit = #north]. exit := cell exitSideFor: #south. self should: [exit = #west]. exit := cell exitSideFor: #west. self should: [exit = #south].! ! !MirrorCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:28'! testCellExitSidesMirrorRight | cell exit | cell := MirrorCell new. cell leanRight. exit := cell exitSideFor: #north. self should: [exit = #west]. exit := cell exitSideFor: #east. self should: [exit = #south]. exit := cell exitSideFor: #south. self should: [exit = #east]. exit := cell exitSideFor: #west. self should: [exit = #north].! ! !MirrorCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:33'! testCellLaserActivityMirrorLeft | cell | cell := MirrorCell leanLeft. cell laserEntersFrom: #north. self should: [cell isOn]. self should: [cell isSegmentOnFor: #north]. self should: [cell isSegmentOnFor: #east]. self shouldnt: [cell isSegmentOnFor: #south]. self shouldnt: [cell isSegmentOnFor: #west]. ! ! !MirrorCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:33'! testCellLaserActivityMirrorRight | cell | cell := MirrorCell leanRight. cell laserEntersFrom: #north. self should: [cell isOn]. self should: [cell isSegmentOnFor: #north]. self should: [cell isSegmentOnFor: #west]. self shouldnt: [cell isSegmentOnFor: #east]. self shouldnt: [cell isSegmentOnFor: #south]. ! ! !MirrorCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:25'! testCellOnState | cell | cell := MirrorCell new. self should: [cell isOff]. self shouldnt: [cell isOn]. ! ! !MirrorCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:26'! testCellSegmentsState | cell | cell := MirrorCell new. self shouldnt: [cell isSegmentOnFor: #north]. self shouldnt: [cell isSegmentOnFor: #east]. self shouldnt: [cell isSegmentOnFor: #south]. self shouldnt: [cell isSegmentOnFor: #west]. ! ! !TargetCell methodsFor: 'initialize-release' stamp: 'sbw 7/23/2007 06:36'! initialize super initialize. self initializeExitSides. ! ! !TargetCell methodsFor: 'initialize-release' stamp: 'sbw 7/23/2007 06:36'! initializeExitSides self exitSides: Dictionary new. self exitSides at: #north put: nil. self exitSides at: #east put: nil. self exitSides at: #south put: nil. self exitSides at: #west put: nil. ! ! !TargetCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:40'! drawCircleOutline | delta offset circle fillForm | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. circle := Circle new. fillForm := Form extent: 2@2 depth: 8. fillForm fillColor: LaserGameColors targetCenterColor. circle form: fillForm. circle radius: 7. circle center: (offset + (delta // 2)). circle displayOn: self targetForm! ! !TargetCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:37'! drawCrossHairsOutlines | inset delta offset x1 x2 y1 y2 fillForm line | inset := 6@6. delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x + inset x. x2 := offset x + delta x - inset x. y1 := offset y + (delta y // 2). y2 := y1. fillForm := Form extent: 2@2 depth: 8. fillForm fillColor: LaserGameColors targetCenterColor. line := Line from: x1@y1 to: x2@y2 withForm: fillForm. line displayOn: self targetForm. x1 := offset x + (delta x // 2). x2 := x1. y1 := offset y + inset y. y2 := offset y + delta y - inset y. fillForm := Form extent: 2@2 depth: 8. fillForm fillColor: LaserGameColors targetCenterColor. line := Line from: x1@y1 to: x2@y2 withForm: fillForm. line displayOn: self targetForm. ! ! !TargetCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:32'! drawTargetOutlines self drawCrossHairsOutlines. self drawCircleOutline! ! !TargetCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:32'! renderContents | cell | cell := self grid at: self cellLocation. self drawTargetOutlines. cell isOn ifTrue: [self renderContentsOn] ifFalse: [self renderContentsOff]! ! !TargetCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:42'! renderContentsOff self renderInnerCircleColor: LaserGameColors targetCenterColorIdle! ! !TargetCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:42'! renderContentsOn self renderInnerCircleColor: LaserGameColors targetCenterColorActive! ! !TargetCellRenderer methodsFor: 'drawing' stamp: 'sbw 7/24/2007 19:45'! renderInnerCircleColor: aColor | delta offset circle fillForm | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. circle := Circle new. fillForm := Form extent: 4@4 depth: 8. fillForm fillColor: aColor. circle form: fillForm. circle radius: 3. circle center: (offset + (delta // 2) - 1). circle displayOn: self targetForm. ! ! !TargetCellRenderer class methodsFor: 'as yet unclassified' stamp: 'sbw 7/24/2007 18:40'! modelClass ^TargetCell! ! !TargetCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:42'! testCellExitSides | cell inputSides | cell := TargetCell new. inputSides := #(#north #east #south #west). inputSides do: [:inputSide | | exit | exit := cell exitSideFor: inputSide. self should: [exit isNil]]! ! !TargetCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:42'! testCellLaserActivity | cell | cell := TargetCell new. cell laserEntersFrom: #north. self should: [cell isOn]. self should: [cell isSegmentOnFor: #north]. self shouldnt: [cell isSegmentOnFor: #south]. self shouldnt: [cell isSegmentOnFor: #east]. self shouldnt: [cell isSegmentOnFor: #west]. ! ! !TargetCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:39'! testCellOnState | cell | cell := TargetCell new. self should: [cell isOff]. self shouldnt: [cell isOn]. ! ! !TargetCellTestCase methodsFor: 'tests' stamp: 'sbw 7/23/2007 06:39'! testCellSegmentsState | cell | cell := TargetCell new. self shouldnt: [cell isSegmentOnFor: #north]. self shouldnt: [cell isSegmentOnFor: #east]. self shouldnt: [cell isSegmentOnFor: #south]. self shouldnt: [cell isSegmentOnFor: #west]. ! ! !TargetCellTestCase reorganize! ('tests' testCellExitSides testCellLaserActivity testCellOnState testCellSegmentsState) ! !TargetCellRenderer reorganize! ('drawing' drawCircleOutline drawCrossHairsOutlines drawTargetOutlines renderContents renderContentsOff renderContentsOn renderInnerCircleColor:) ! !TargetCell reorganize! ('initialize-release' initialize initializeExitSides) ! !MirrorCellTestCase reorganize! ('tests' testCellExitSidesMirrorLeft testCellExitSidesMirrorRight testCellLaserActivityMirrorLeft testCellLaserActivityMirrorRight testCellOnState testCellSegmentsState) ! !MirrorCellRenderer reorganize! ('drawing' cornerInset renderContents renderContentsLeanLeft renderContentsLeanRight) ! !MirrorCell class reorganize! ('instance creation' leanLeft leanRight) ! !MirrorCell reorganize! ('accessing' leanLeft leanRight leansLeft leansLeft:) ('testing' isLeft isRight) ('initialize-release' initialize initializeExitSides) ! !LaserGame reorganize! ('accessing' boardForm boardForm: grid grid:) ('constants' calculatedExtent panelWidth setExtent) ('drawing' drawGameBoard) ('initialization' findFireButton fireButtonLabel fireLaser initialize laserActive makeButton:action:state: makeControlPanelMorph makeFireLaserButton makeGameBoardMorph makeQuitGameButton quitGame setupMorphs updateFireButtonLabel) ! !GridTestCase reorganize! ('private' generateDemoGrid) ('tests' testCellInteractions testFireLaser testInitialConditions testNonDefaultGridSizeConditions testStopLaser testToggleLaser) ! !GridDirectionTestCase reorganize! ('tests' testDirectionSelection) ! !Grid class reorganize! ('instance creation' newOfSize:) ! !Grid reorganize! ('accessing' activateCellsInPath at: at:put: calculatePath cells cells: laserBeamPath laserBeamPath: laserIsActive laserIsActive: numberOfColumns numberOfColumns: numberOfRows numberOfRows: startingCell) ('initialize-release' initialize initializeCells) ('as yet unclassified' clearCellsInPath fireLaser stopLaser) ! !CellRendererTestCase reorganize! ('tests' testCellOffsetCalculations testRenderSelection) ! !CellRenderer reorganize! ('accessing' cellLocation cellLocation: grid grid: offsetWithinGridForm targetForm targetForm:) ('drawing' render renderBorder renderBorderBottom renderBorderLeft renderBorderRight renderBorderTop renderContents) ! BlankCell removeSelector: #activeSegments! BlankCell removeSelector: #activeSegments:! BlankCell removeSelector: #exitSideFor:! BlankCell removeSelector: #exitSides! BlankCell removeSelector: #exitSides:! BlankCell removeSelector: #initializeActiveSegments! BlankCell removeSelector: #isOff! BlankCell removeSelector: #isOn! BlankCell removeSelector: #isSegmentOnFor:! BlankCell removeSelector: #laserEntersFrom:! !BlankCell reorganize! ('initialize-release' initialize initializeExitSides) ! !Cell reorganize! ('initialize-release' initialize initializeActiveSegments) ('accessing' activeSegments activeSegments: clearCell exitSideFor: exitSides exitSides: gridLocation gridLocation: laserEntersFrom:) ('testing' isOff isOn isSegmentOnFor:) ! !BlankCellTestCase reorganize! ('tests' testCellExitSides testCellLaserActivity testCellOnState testCellSegmentsState) ! !Object reorganize! ('accessing' addInstanceVarNamed:withValue: at: at:modify: at:put: basicAddInstanceVarNamed:withValue: basicAt: basicAt:put: basicSize bindWithTemp: ifNil:ifNotNilDo: ifNotNilDo: ifNotNilDo:ifNil: in: presenter readFromString: size yourself) ('associating' ->) ('Breakpoint') ('binding' bindingOf:) ('casing' caseOf: caseOf:otherwise:) ('class membership' class inheritsFromAnyIn: isKindOf: isKindOf:orOf: isMemberOf: respondsTo: xxxClass) ('comparing' closeTo: hash hashMappedBy: identityHashMappedBy: identityHashPrintString literalEqual: = ~=) ('converting' adaptToFloat:andSend: adaptToFraction:andSend: adaptToInteger:andSend: asActionSequence asActionSequenceTrappingErrors asDraggableMorph asOrderedCollection asString asStringOrText as: complexContents mustBeBoolean mustBeBooleanIn: printDirectlyToDisplay withoutListWrapper) ('copying' clone copy copyAddedStateFrom: copyFrom: copySameFrom: copyTwoLevel deepCopy initialDeepCopierSize postCopy shallowCopy veryDeepCopy veryDeepCopySibling veryDeepCopyUsing: veryDeepCopyWith: veryDeepFixupWith: veryDeepInner:) ('creation' asMorph asStringMorph asTextMorph openAsMorph) ('debugging' haltIf: needsWork) ('debugging-haltOnce' checkHaltCountExpired clearHaltOnce decrementAndCheckHaltCount decrementHaltCount doExpiredHaltCount doExpiredHaltCount: doExpiredInspectCount haltOnCount: haltOnce haltOnceEnabled haltOnce: halt:onCount: hasHaltCount inspectOnCount: inspectOnce inspectUntilCount: removeHaltCount setHaltCountTo: setHaltOnce toggleHaltOnce) ('dependents access' addDependent: breakDependents canDiscardEdits dependents evaluate:wheneverChangeIn: hasUnacceptedEdits myDependents myDependents: release removeDependent:) ('drag and drop' acceptDroppingMorph:event:inMorph: dragAnimationFor:transferMorph: dragPassengerFor:inMorph: dragTransferType dragTransferTypeForMorph: wantsDroppedMorph:event:inMorph:) ('error handling' assert: assert:descriptionBlock: assert:description: backwardCompatibilityOnly: caseError confirm: confirm:orCancel: deprecated: deprecated:block: doesNotUnderstand: dpsTrace: dpsTrace:levels: dpsTrace:levels:withContext: error error: explicitRequirement halt halt: handles: notifyWithLabel: notify: notify:at: primitiveFailed requirement shouldBeImplemented shouldNotImplement subclassResponsibility traitConflict) ('evaluating' value valueWithArguments:) ('events-accessing' actionForEvent: actionForEvent:ifAbsent: actionMap actionSequenceForEvent: actionsDo: createActionMap hasActionForEvent: setActionSequence:forEvent: updateableActionMap) ('events-registering' when:evaluate: when:send:to: when:send:to:withArguments: when:send:to:with:) ('events-removing' releaseActionMap removeActionsForEvent: removeActionsSatisfying: removeActionsSatisfying:forEvent: removeActionsWithReceiver: removeActionsWithReceiver:forEvent: removeAction:forEvent:) ('events-triggering' triggerEvent: triggerEvent:ifNotHandled: triggerEvent:withArguments: triggerEvent:withArguments:ifNotHandled: triggerEvent:with: triggerEvent:with:ifNotHandled:) ('filter streaming' byteEncode: drawOnCanvas: elementSeparator encodePostscriptOn: flattenOnStream: fullDrawPostscriptOn: printOnStream: putOn: storeOnStream: writeOnFilterStream:) ('finalization' actAsExecutor executor finalizationRegistry finalize retryWithGC:until: toFinalizeSend:to:with:) ('flagging' isThisEverCalled isThisEverCalled: logEntry logExecution logExit) ('graph model' addModelYellowButtonMenuItemsTo:forMorph:hand: hasModelYellowButtonMenuItems) ('locales' localeChanged) ('macpal' codeStrippedOut: contentsChanged currentEvent currentHand currentVocabulary currentWorld flash instanceVariableValues isUniversalTiles objectRepresented refusesToAcceptCode scriptPerformer slotInfo) ('message handling' executeMethod: perform: perform:orSendTo: perform:withArguments: perform:withArguments:inSuperclass: perform:withEnoughArguments: perform:with: perform:with:with: perform:with:with:with: withArgs:executeMethod: with:executeMethod: with:with:executeMethod: with:with:with:executeMethod: with:with:with:with:executeMethod:) ('objects from disk' comeFullyUpOnReload: convertToCurrentVersion:refStream: fixUponLoad:seg: indexIfCompact objectForDataStream: readDataFrom:size: saveOnFile storeDataOn:) ('parts bin' descriptionForPartsBin) ('printing' fullPrintString isLiteral longPrintOn: longPrintOn:limitedTo:indent: longPrintString longPrintStringLimitedTo: nominallyUnsent: printOn: printString printStringLimitedTo: propertyList reportableSize storeOn: storeString stringForReadout stringRepresentation) ('scripting' adaptedToWorld: defaultFloatPrecisionFor: evaluateUnloggedForSelf: methodInterfacesForCategory:inVocabulary:limitClass: methodInterfacesForInstanceVariablesCategoryIn: methodInterfacesForScriptsCategoryIn: selfWrittenAsIll selfWrittenAsIm selfWrittenAsMe selfWrittenAsMy selfWrittenAsThis) ('self evaluating' isSelfEvaluating) ('system primitives' asOop becomeForward: becomeForward:copyHash: className creationStamp instVarAt: instVarAt:put: instVarNamed: instVarNamed:put: oopString primitiveChangeClassTo: rootStubInImageSegment: someObject) ('testing' basicType beViewed costumes haltIfNil hasLiteralSuchThat: hasLiteralThorough: haveFullProtocolBrowsed haveFullProtocolBrowsedShowingSelector: isArray isBehavior isBlock isBlockClosure isCharacter isCollection isColor isColorForm isCompiledMethod isComplex isDictionary isFloat isForm isFraction isHeap isInteger isInterval isMessageSend isMethodProperties isMorph isMorphicEvent isMorphicModel isNumber isPoint isPseudoContext isRectangle isSketchMorph isStream isString isSymbol isSystemWindow isText isTrait isTransparent isVariableBinding isWebBrowser knownName name nameForViewer notNil openInstanceBrowserWithTiles renameInternal: renameTo: showDiffs stepAt:in: stepIn: stepTime stepTimeIn: vocabularyDemanded wantsDiffFeedback wantsSteps wantsStepsIn:) ('translation support' inline: var:declareC:) ('undo' capturedState commandHistory purgeAllCommands redoFromCapturedState: refineRedoTarget:selector:arguments:in: refineUndoTarget:selector:arguments:in: rememberCommand: rememberUndoableAction:named: undoFromCapturedState:) ('updating' changed changed: changed:with: handledListVerification noteSelectionIndex:for: okToChange updateListsAndCodeIn: update: update:with: windowIsClosing) ('user interface' addModelItemsToWindowMenu: addModelMenuItemsTo:forMorph:hand: asExplorerString defaultBackgroundColor defaultLabelForInspector eToyStreamedRepresentationNotifying: explore fullScreenSize hasContentsInExplorer inform: initialExtent inspectWithLabel: launchPartVia: launchPartVia:label: launchTileToRefer modelSleep modelWakeUp modelWakeUpIn: mouseUpBalk: newTileMorphRepresentative notYetImplemented windowActiveOnFirstClick windowReqNewLabel:) ('world hacking' couldOpenInMorphic) ('*39Deprecated' beep beepPrimitive beep: contentsGetz: deprecatedExplanation: deprecated:explanation: doIfNotNil: ifKindOf:thenDo: playSoundNamed:) ('*eToys-accessing') ('*eToys-macpal') ('*eToys-scripting') ('*eToys-testing') ('*eToys-user interface') ('*eToys-viewer') ('*eToys-*Morphic-Scripting') ('*eToys-*Morphic-Tile Scriptors') ('*flexiblevocabularies-viewer') ('*Morphic-Worlds') ('*monticello' isConflict) ('*services-base' requestor) ('*system-support' systemNavigation) ('*Tools-Explorer' exploreAndYourself exploreWithLabel:) ('*Tools-Inspector') ('*Tools-MethodFinder') ('*Traits') ('*tools-browser' browse browseHierarchy) ('private' errorImproperStore errorNonIntegerIndex errorNotIndexable errorSubscriptBounds: primitiveError: species storeAt:inTempFrame:) ('*Morphic-NewCurve-testing''' isNonZero) ('events' actionsWithReceiver:forEvent: renameActionsWithReceiver:forEvent:toEvent:) ('viewer' assureUniClass belongsToUniClass browseOwnClassSubProtocol categoriesForViewer: categoriesForVocabulary:limitClass: chooseNewNameForReference defaultLimitClassForVocabulary: defaultNameStemForInstances elementTypeFor:vocabulary: externalName graphicForViewerTab hasUserDefinedSlots infoFor:inViewer: initialTypeForSlotNamed: isPlayerLike methodInterfacesInPresentationOrderFrom:forCategory: newScriptorAround: offerViewerMenuForEvt:morph: offerViewerMenuFor:event: renameScript: tilePhrasesForCategory:inViewer: tilePhrasesForMethodInterfaces:inViewer: tilePhrasesForSelectorList:inViewer: tileToRefer uniqueInstanceVariableNameLike:excluding: uniqueNameForReference uniqueNameForReferenceFrom: uniqueNameForReferenceOrNil updateThresholdForGraphicInViewerTab usableMethodInterfacesIn:) ('inspecting' basicInspect inspect inspectorClass) ('thumbnail' iconOrThumbnailOfSize:) ('scripts-kernel' universalTilesForGetterOf: universalTilesForInterface:) ('breakpoint' break) ('*FFI') ('*omnibrowser-converting' asAnnouncement) ('*Laser-Game-Model' revisit:) !