I've been playing the game Portal (
http://en.wikipedia.org/wiki/Portal_(video_game)) for the last few months
and it has to be one of the best 3D games I have seen, right up there with
Spore as far as I am concerned. One of the things that intrigues me about
this game is that it looks like it could have been inspired by Croquet,
although it wasn't. So now in the next few weeks, a new collaborative
version of Portal is coming out, which should prove to be lots of fun.
I would think that it would be almost trivial to build the basis of this
game in Cobalt/Croquet and thereby have multiplayer capability right in the
first iteration. But what kind of puzzles of this type would be interesting
for an undetermined number of players greater than 1? This project sounds
interesting enough to me that it could be worthwhile to get back into the
Croquet/Cobalt community. My concern is that the Cobalt/Croquet base still
may not be up to the performance and stability standards that would be
needed for a project like this.
Unfortunately I recently lost all the Croquet stuff that I had locally, so
whatever is out there on SqueakMap and such is all there is of my work. The
biggest loss as far as I am concerned is the work I had done on making Tweak
the main development environment so that Morphic wasn't needed anymore. It
was never finished and so never released.
So why am I writing this? I'm not exactly sure, but maybe it has something
to do with finding collaborators to build a new Portal-like game in
Cobalt/Croquet and a little inspiration for puzzles. Convince me this
sounds like a good idea!
Cheers,
Dave
Nicolas Cellier uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-nice.305.mcz
==================== Summary ====================
Name: Tools-nice.305
Author: nice
Time: 2 April 2011, 9:41:26.838 pm
UUID: 9e3c6b7c-7e5f-485b-b625-47f8d2345edd
Ancestors: Tools-nice.304, Tools-eem.304
Merge
=============== Diff against Tools-nice.304 ===============
Item was changed:
----- Method: Debugger>>browseMessages (in category 'context stack menu') -----
browseMessages
"Present a menu of all messages sent by the currently selected message.
Open a message set browser of all implementors of the message chosen.
Do nothing if no message is chosen."
contextStackIndex = 0 ifTrue: [^ self].
+ self withSelectorAndMessagesIn: self selectedContext method
- self withSelectorAndMessagesIn: currentCompiledMethod
evaluate: [:selector| self systemNavigation browseAllImplementorsOf: selector]!
Item was changed:
----- Method: Debugger>>browseSendersOfMessages (in category 'context stack menu') -----
browseSendersOfMessages
"Present a menu of the currently selected message, as well as all
messages sent by it. Open a message set browser of all senders
of the message chosen."
contextStackIndex = 0 ifTrue: [^ self].
+ self withSelectorAndMessagesIn: self selectedContext method
- self withSelectorAndMessagesIn: currentCompiledMethod
evaluate: [:selector| self systemNavigation browseAllCallsOn: selector]!
Item was changed:
----- Method: Debugger>>contents:notifying: (in category 'accessing') -----
contents: aText notifying: aController
"The retrieved information has changed and its source must now be updated.
In this case, the retrieved information is the method of the selected context."
| result selector classOfMethod category h ctxt newMethod |
contextStackIndex = 0 ifTrue:
[^false].
self selectedContext isExecutingBlock ifTrue:
[h := self selectedContext activeHome.
h ifNil:
[self inform: 'Method for block not found on stack, can''t edit and continue'.
^false].
(self confirm: 'I will have to revert to the method from\which this block originated. Is that OK?' withCRs) ifFalse:
[^false].
self resetContext: h.
+ "N.B. Only reset the contents if the compilation succeeds. If contents are reset
+ when compilation fails both compiler error message and modifications are lost."
+ (result := self contents: aText notifying: aController) ifTrue:
+ [self contentsChanged].
- result := self contents: aText notifying: aController.
- self contentsChanged.
^result].
classOfMethod := self selectedClass.
category := self selectedMessageCategoryName.
selector := self selectedClass newParser parseSelector: aText.
(selector == self selectedMessageName
or: [(self selectedMessageName beginsWith: 'DoIt')
and: [selector numArgs = self selectedMessageName numArgs]]) ifFalse:
[self inform: 'can''t change selector'.
^false].
selector := classOfMethod
compile: aText
classified: category
notifying: aController.
selector ifNil: [^false]. "compile cancelled"
contents := aText.
newMethod := classOfMethod compiledMethodAt: selector.
newMethod isQuick ifTrue:
[self down.
self selectedContext jump: (self selectedContext previousPc - self selectedContext pc)].
ctxt := interruptedProcess popTo: self selectedContext.
ctxt == self selectedContext
ifFalse:
[self inform: 'Method saved, but current context unchanged\because of unwind error. Click OK to see error' withCRs]
ifTrue:
[newMethod isQuick ifFalse:
[interruptedProcess
restartTopWith: newMethod;
stepToSendOrReturn].
contextVariablesInspector object: nil].
self resetContext: ctxt.
Smalltalk isMorphic ifTrue:
[World
addAlarm: #changed:
withArguments: #(contentsSelection)
for: self
at: (Time millisecondClockValue + 200)].
^true!
Nicolas Cellier uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-nice.304.mcz
==================== Summary ====================
Name: Tools-nice.304
Author: nice
Time: 31 March 2011, 10:13:14.329 pm
UUID: 6046b00a-2861-4da3-9dc2-ab9ce2f41496
Ancestors: Tools-nice.303
remove some FakeClassPool and #failedDoit references parce qu'elles le valent bien.
=============== Diff against Tools-nice.303 ===============
Item was changed:
----- Method: Browser>>doItReceiver (in category 'accessing') -----
doItReceiver
"This class's classPool has been jimmied to be the classPool of the class
being browsed. A doIt in the code pane will let the user see the value of
the class variables."
+ ^ self selectedClass!
- ^ self selectedClass ifNil: [FakeClassPool new]!
Item was changed:
----- Method: Inspector>>accept: (in category 'selecting') -----
accept: aString
| result |
result := self doItReceiver class evaluatorClass new
evaluate: (ReadStream on: aString)
in: self doItContext
to: self doItReceiver
notifying: nil "fix this"
ifFail: [self changed: #flash.
^ false].
- result == #failedDoit ifTrue: [^ false].
self replaceSelectionValue: result.
self changed: #contents.
^ true!
Item was changed:
----- Method: MethodHolder>>doItReceiver (in category 'menu') -----
doItReceiver
"If there is an instance associated with me, answer it, for true mapping of self. If not, then do what other code-bearing tools do, viz. give access to the class vars."
+ ^ self selectedClass!
- ^ self selectedClass ifNil: [FakeClassPool new]!
Nicolas Cellier uploaded a new version of ST80 to project The Trunk:
http://source.squeak.org/trunk/ST80-nice.127.mcz
==================== Summary ====================
Name: ST80-nice.127
Author: nice
Time: 31 March 2011, 10:05:15.793 pm
UUID: 04b556c6-fdea-46d0-b21a-9160ebd94302
Ancestors: ST80-nice.126
Get rid of FakeClassPool and #failedDoIt references.
This is implemented by the mean of #evaluateSelectionAndDo:
This method will pass the result to aBlock argument in case of success, and avoid testing for arbitrary return value (FakeClassPool new or #failedDoit)
=============== Diff against ST80-nice.126 ===============
Item was changed:
----- Method: ParagraphEditor>>evaluateSelection (in category 'do-its') -----
evaluateSelection
"Treat the current selection as an expression; evaluate it and return the result"
+
+ ^self evaluateSelectionAndDo: [:result | result]!
- | result rcvr ctxt |
- self lineSelectAndEmptyCheck: [^ ''].
-
- (model respondsTo: #doItReceiver)
- ifTrue: [ rcvr := model doItReceiver.
- ctxt := model doItContext]
- ifFalse: [rcvr := ctxt := nil].
- result := [
- rcvr class evaluatorClass new
- evaluate: self selectionAsStream
- in: ctxt
- to: rcvr
- notifying: self
- ifFail: [^ #failedDoit]
- logged: true.
- ]
- on: OutOfScopeNotification
- do: [ :ex | ex resume: true].
- ^ result!
Item was added:
+ ----- Method: ParagraphEditor>>evaluateSelectionAndDo: (in category 'do-its') -----
+ evaluateSelectionAndDo: aBlock
+ "Treat the current selection as an expression; evaluate it and invoke aBlock with the result."
+ | result rcvr ctxt |
+ self lineSelectAndEmptyCheck: [^ nil].
+
+ (model respondsTo: #doItReceiver)
+ ifTrue: [ rcvr := model doItReceiver.
+ ctxt := model doItContext]
+ ifFalse: [rcvr := ctxt := nil].
+ result := [
+ rcvr class evaluatorClass new
+ evaluate: self selectionAsStream
+ in: ctxt
+ to: rcvr
+ notifying: self
+ ifFail: [self flash. ^nil]
+ logged: true.
+ ]
+ on: OutOfScopeNotification
+ do: [ :ex | ex resume: true].
+ ^aBlock value: result!
Item was changed:
----- Method: ParagraphEditor>>exploreIt (in category 'do-its') -----
exploreIt
+ self evaluateSelectionAndDo: [:result | result explore]
- | result |
- result := self evaluateSelection.
- ((result isKindOf: FakeClassPool) or: [result == #failedDoit])
- ifTrue: [view flash]
- ifFalse: [result explore].
!
Item was changed:
----- Method: ParagraphEditor>>inspectIt (in category 'do-its') -----
inspectIt
+ self evaluateSelectionAndDo: [:result | result inspect].
- "1/13/96 sw: minor fixup"
- | result |
- result := self evaluateSelection.
- ((result isKindOf: FakeClassPool) or: [result == #failedDoit])
- ifTrue: [view flash]
- ifFalse: [result inspect].
!
Item was changed:
----- Method: ParagraphEditor>>objectsReferencingIt (in category 'do-its') -----
objectsReferencingIt
"Open a list inspector on all objects that reference the object that results when the current selection is evaluated. "
+ self terminateAndInitializeAround:
+ [self evaluateSelectionAndDo: [:result |
+ self systemNavigation
- self terminateAndInitializeAround: [ | result |
- result := self evaluateSelection.
- ((result isKindOf: FakeClassPool) or: [result == #failedDoit])
- ifTrue: [view flash]
- ifFalse: [self systemNavigation
browseAllObjectReferencesTo: result
except: #()
+ ifNone: [:obj | view topView flash]]]!
- ifNone: [:obj | view topView flash]].
- ]!
Item was changed:
----- Method: ParagraphEditor>>printIt (in category 'do-its') -----
printIt
"Treat the current text selection as an expression; evaluate it. Insert the
description of the result of evaluation after the selection and then make
this description the new text selection."
+ self evaluateSelectionAndDo: [:result |
+ self afterSelectionInsertAndSelect: result printString]!
- | result |
- result := self evaluateSelection.
- ((result isKindOf: FakeClassPool) or: [result == #failedDoit])
- ifTrue: [view flash]
- ifFalse: [self afterSelectionInsertAndSelect: result printString]!
Item was changed:
----- Method: ParagraphEditor>>tallySelection (in category 'do-its') -----
tallySelection
"Treat the current selection as an expression; evaluate it and return the time took for this evaluation"
| result rcvr ctxt valueAsString v |
+ self lineSelectAndEmptyCheck: [^self].
- self lineSelectAndEmptyCheck: [^ -1].
(model respondsTo: #doItReceiver)
ifTrue: [ rcvr := model doItReceiver.
ctxt := model doItContext]
ifFalse: [rcvr := ctxt := nil].
result := [ | cm |
cm := rcvr class evaluatorClass new
compiledMethodFor: self selectionAsStream
in: ctxt
to: rcvr
notifying: self
+ ifFail: [self flash. ^self]
- ifFail: [^ #failedDoit]
logged: false.
Time millisecondsToRun:
[v := cm valueWithReceiver: rcvr arguments: #() ].
]
on: OutOfScopeNotification
do: [ :ex | ex resume: true].
"We do not want to have large result displayed"
valueAsString := v printString.
(valueAsString size > 30) ifTrue: [valueAsString := (valueAsString copyFrom: 1 to: 30), '...'].
PopUpMenu
inform: 'Time to compile and execute: ', result printString, 'ms res: ', valueAsString.
!
Nicolas Cellier uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-nice.205.mcz
==================== Summary ====================
Name: Compiler-nice.205
Author: nice
Time: 2 April 2011, 7:27:35.803 pm
UUID: 1ff62b57-d6e2-43b6-8827-db4113196b24
Ancestors: Compiler-ul.204
Don't forget to deoptimize the receiver of an optimized message in case of cascade.
=============== Diff against Compiler-ul.204 ===============
Item was changed:
----- Method: MessageNode>>ensureCanCascade: (in category 'testing') -----
ensureCanCascade: encoder
special > 0 ifTrue:
[special := 0.
selector := encoder encodeSelector: originalSelector.
arguments := originalArguments.
+ receiver isBlockNode ifTrue: [receiver deoptimize].
arguments do:
[:each|
each isBlockNode ifTrue:
[each deoptimize]]]!
Jason,
On Tue, Mar 29, 2011, Casey Ransberger wrote:
> WRT Morphic and direct user interface construction: this isn't fantasy. You
> can actually do this today, as it was one of the original drivers for the
> system when it was conceived in Self, as an evolution of Randall Smith's
> Smalltalk based Alternate Reality Toolkit (ARK.)
I agree with Casey: it is not fantasy.
However, with Squeak / Pharo, direct manipulation gets you _instances_
of morphs. To fit the Smalltalk programming paradigm, you need a class
and methods (at least a drawOn: method, but probably some event
handlers too.) Direct manipulation doesn't quite get you the code (in
the way Interface Builder does.)
But ...
(1) You can probably figure out the code using an inspector and a
little arithmetic.
(2) Morphic Players get real Smalltalk code behind them that you can
see in your changeset browser.
(3) Have you seen this yet?
http://www.jarober.com/blog/blogView?showComments=true&printTitle=ST_4U_53:…
David