How do I animate a morph without using step? - smalltalk

I want to animate a dice being rolled, but don't want to use the Morph>>step methods because I want more control over when the roll finishes. I know that I can use Delay>>wait within a forked block to see my animation, but then how should I call this method from other methods to ensure I get the final numberRolled?
Here's my roll method:
roll
| n t |
numberRolled := nil.
[
t := 10 + (10 atRandom).
t timesRepeat: [
n := 6 atRandom.
self showNumber: n.
(Delay forSeconds: 0.1) wait.
].
numberRolled := n.
] fork.
So if I call this from a method like guessLower the roll method returns instantly because the real work is completed in the forked process.
guessLower
previousNumberRolled := numberRolled.
self roll.
"this next line is called before the dice has finished rolling"
self checkWin: (numberRolled < previousNumberRolled)
My current solution is to modify roll method to take a block, which that executes after the rolling has finished e.g. rollAndThen: aBlock but is there a more elegant / simpler solution?

In Morphic it is a Really Bad Idea to use Delays and explicit looping.
But it is really simple to make the step method do what you want: Inside you simply check if it should continue rolling or not. Then you do self stopStepping. self checkWin: ....

Related

How can I store a code block in a variable and call it and get its return value whenever needed?

I'm making a little text adventure in Smalltalk. It's made up of "screens" that have their texts and choices for other screens included. Since I want the game to be dynamic, I also want to include branching. For instance, if the player is at a blacksmith and wants to buy an axe, the screen the player goes to immediately checks if the player has enough money and jumps to one of two other screens based on that.
I already have this working: The screens (classes named Place) have a list where the first item is the function and the following items are the arguments. However, I have it done in a very ugly way: the first item is a string that is then compared against in a big "action" method, so it looks something like this:
game data method:
blacksmith := Place new.
blacksmith choiceText: 'I would like an axe.';
blacksmith action add: 'money'; add: 20; add: blacksmith_good; add: blacksmith_bad.
action method: (currentScreen is also a Place; the class also contains a BranchMoney method that does the actual decision making)
(currentScreen action at: 1) = 'money'
ifTrue: [
currentScreen := (currentScreen BranchMoney)
]
That's obviously not ideal, and I would like to compact it by doing something like this:
game data method:
blacksmith action add: [blacksmith BranchMoney]; add: 20; add: blacksmith_good; add: blacksmith_bad.
action method:
currentScreen := (currentScreen action at: 1)
So that instead of string checking the game would just directly proceed with the method I want it to do.
However, it doesn't seem to work - I've tried different changes to the code, and the problem seems to be that the currentScreen := (currentScreen action at: 1) line just replaces the contents of currentScreen with the code block contents – it doesn't calculate the block's contents and use its resulting value that is of type Place.
I've tried using round brackets in the game data method – that throws a list out of bounds exception, because it tries to calculate the expression immediately, before other arguments have even been added. Changing the first item name in game data method to currentScreen BranchMoney doesn't seem to make a difference.
I've also tried adding a return in the game data method, like this: blacksmith action add: [^blacksmith BranchMoney], so that it would have a value to return, no luck. Doing something like currentScreen := [^currentScreen action at: 1] in the action method doesn't work either.
For some shots in the dark, I tried the ExternalProcedure call and call: methods, but that failed too.
In Smalltalk every block is a regular object that you can store and retrieve the same you would do with any other object:
b := [self doSomething]
stores in b the block (much as b := 'Hello' stores a string in b). What I think you are missing is the #value message. To execute the block do the following
b value "execute self doSomething and answer with the result"
In case your block has one argument use #value: instead
b := [:arg | self doSomethingWith: arg]
later on
b value: 17 "execute the block passing 17 as the argument"
(for two arguments use #value:value:, for three #value:value:value: and for many #valueWithArguments:.)
Note however that this approach of using blocks and Arrays of arguments doesn't look very elegant (or even convenient). However, to help you with some better alternative we would need to learn more about your game. So, go check whether #value (and friends) let you progress a little bit and feel free to come back here with your next question. After some few iterations we could guide you towards a clearer route.
Example
b := [:m | m < 20 ifTrue: ['bad'] ifFalse: ['good']].
will produce
b value: 15 "==> 'bad'"
b value: 25 "==> 'good'"

Can one create a standalone method/function (without any class)

I am trying to understand smalltalk. Is it possible to have a standalone method/function, which is not part of any particular class, and which can be called later:
amethod ['amethod called' printNl].
amethod.
Above code gives following error:
simpleclass.st:1: expected Eval, Namespace or class definition
How can I use Eval or Namespace as being suggested by error message?
I tried following but none work:
Eval amethod [...
amethod Eval [...
Eval amethod Eval[... "!"
Eval [... works but I want to give a name to the block so that I can call it later.
Following also works but gets executed immediately and does not execute when called later.
Namespace current: amethod ['amethod called' printNl].
Thanks for your insight.
In Smalltalk the equivalent to a standalone method is a Block (a.k.a. BlockClosure). You create them by enclosing Smalltalk expressions between square brackets. For example
[3 + 4]
To evaluate a block, you send it the message value:
[3 + 4] value
which will answer with 7.
Blocks may also have arguments:
[:s | 3 + s]
you evaluate them with value:
[:s | 3 + s] value: 4 "answers with 7"
If the block has several sentences, you separate them with a dot, as you would do in the body of a method.
Addendum
Blocks in Smalltalk are first class objects. In particular, one can reference them with variables, the same one does with any other objects:
three := 3.
threePlus := [:s | three + s].
for later use
threePlus value: 4 "7"
Blocks can be nested:
random := Random new.
compare := [:p :u | u <= p]
bernoulli60 := [compare value: 0.6 value: random next].
Then the sequence:
bernoulli60 value. "true"
bernoulli60 value. "false"
...
bernoulli60 value. "true"
will answer with true about 60% of the times.
Leandro's answer, altough being correct and with deep smalltalk understanding, is answering what you asked for, but I think, not 100% sure thou, you are actually asking how to "play" around with a code without the need to create a class.
In my eyes want you want is called a Workspace (Smalltalk/X and Dolphin) (it can have different names like Playground in Pharo Smalltalk).
If you want to play around you need to create a local variable.
| result |
result := 0. "Init otherwise nil"
"Adding results of a simple integer factorial"
1 to: 10 do: [ :integer |
result := result + integer factorial
].
Transcript show: result.
Explanation:
I'm using a do: block for 1-10 iterration. (:integer is a block local variable). Next I'm, showing the result on Transcript.

Squeak Smalltalk: Game loop

In many languages you can do something like the following:
while true:
handle events like keyboard input
update game world
draw screen
(optional: delay execution)
while this is far from optimal it should suffice for simple games.
How do you do this in Squeak Smalltalk?
I can read keyboard input and react to it as described on wiki.squeak.org. But if I try to execute something like
1 to: 10 do: [ :i | game updateAndDraw ]
all the events are only ever handled after the loop has executed.
Morphic already provides that main loop. It's in MorphicProject class>>spawnNewProcess:
uiProcess := [
[ world doOneCycle. Processor yield ] repeat.
] newProcess ...
And if you dig into doOneCycle you will find it
(optionally) does a delay (interCyclePause:)
checks for screen resize
processes events
processes step methods
re-displays the world
Your code should hook into these phases by adding mouse/keyboard event handlers, step methods for animation, and draw methods for redisplaying. All of these should be methods in your own game morph. You can find examples throughout the system.
To perform an action a fixed number of times:
10 timesRepeat: [game updateAndDraw]
To use while semantics:
i := 5
[i > 0] whileTrue: [
i printNl.
i := i - 1.
]
To create a perpetual loop using while semantics,
[true] whileTrue: [something do]
You should be able to take advantage of the Morphic event loop by using the Object >> #when:send:to: message.

Sleep blocks whole program (Smalltalk Squeak)

I'm making a N*N queens problem with gui.
I want the gui to stop for x seconds each move of every queen, problem is, the program just stacks all the waits together and then runs everything at speed.
I'm giving the code here: http://pastebin.com/s2VT0E49
EDIT:
This is my workspace:
board := MyBoard new initializeWithStart: 8.
Transcript show:'something'.
3 seconds asDelay wait.
board solve.
3 seconds asDelay wait.
board closeBoard.
This is where i want the wait to happen
canAttack: testRow x: testColumn
| columnDifference squareMark |
columnDifference := testColumn - column.
((row = testRow
or: [row + columnDifference = testRow])
or: [row - columnDifference = testRow]) ifTrue: [
squareDraw := squareDraw
color: Color red.
0.2 seconds asDelay wait.
^ true ].
squareDraw := squareDraw color: Color black.
^ neighbor canAttack: testRow x: testColumn
Since you're using Morphic you should use stepping for animation, not processes or delays. In your Morph implement a step method. This will be executed automatically and repeatedly. Also implement stepTime to answer the interval in milliseconds, e.g. 4000 for every 4 seconds.
Inside the step method, calculate your new state. If each queen is modeled as a separate Morph and you just move the positions, then Morphic will take care of updating the screen. If you have your own drawOn: method then call self changed in your step method so that Morphic will later invoke your drawing code.
See this tutorial: http://static.squeak.org/tutorials/morphic-tutorial-1.html
The process you're suspending is the one your program is running in. This process also happens to be the UI process. So when you suspend your program you also suspend the UI and therefore the UI elements never get a chance to update themselves. Try running your program in a separate process:
[ MyProgram run ] forkAt: Processor userBackgroundPriority.
Note that the UI process usually runs at priority 40. #userBackgroundPriority is 30. This makes sure that you can't lock up the UI.
To make your workspace code work insert this before the delay:
World doOneCycle.
This will cause the Morphic world to be redisplayed.
Note that this is quick-and-very-dirty hack and not the proper way to do it (see my other answer). Delays block the whole UI process, whereas the whole point of Morphic is that you can do many things simultaneously while your code is executing.

PLC Object Oriented Programming - Using methods

I'm writing a program for a Schneider PLC using structured text, and I'm trying to do it using object oriented programming.
Being a newbie in PLC programming, I wrote a simple test program such a this:
okFlag:=myObject.aMethod();
IF okFlag THEN
// it's ok, go on
ELSE
// error handling
END_IF
aMethod must perform some operations, wait for the result (there is a "time-out" check to avoid deadlocks) and return TRUE or FALSE
This is what I expected during program execution
1) when the okFlag:=myObject.aMethod(); is reached, the code inside aMethod is executed until a result is returned. When I say "executed" I mean that in the next scan cycle the execution of aMethodcontinues from the point it had reached before.
2) the result of method calling is checked and the main flow of the program is executed
and this is what happens:
1) aMethod is executed but the program flow continues. That is, when it reaches the end of aMethod a value it's returned, even if the events that aMethod should wait for are still executing.
2) on the next cycle, aMethod is called again and restarts from the beginning
This is the first solution I found:
VAR_STATIC
imBusy: BOOL
END_VAR
METHOD aMethod: INT;
IF NOT(imBusy) THEN
imBusy:=FALSE;
aMethod:=-1; // result of method while in progress
ELSE
aMethod:=-1;
<rest of code. If everything is ok, the result is 0, otherwise is 1>
END_IF
imBusy:=aMethod<0;
and the main program:
CASE (myObject.aMethod()) OF
0: // it's ok, go on
1: // error handling
ELSE
// still executing...
END_CASE
and this seems to work, but I don't know if it's the right approach.
There are some libraries from Schneider which use methods that return boolean and seem to work as I expected in my program. That is: when the cycle reaches the call to method for the first time the program flow is "deviated" somehow so that in the next cycle it enters again the method until it's finished. It's there a way to have this behaviour ?
generally OOP isn't the approach that people would take when using IEC61131 languages. Your best bet is probably to implement your code as a state machine. I've used this approach in the past as a way of simplifying a complex sequence so that it is easier for plant maintainers to interpret.
Typically what I would recommend if you are going to take this approach is to try to segregate your state machine itself from your working code; you can implement a state machine of X steps, and then have your working code reference the statemachine step.
A simple example might look like:
stepNo := 0;
IF (start AND stepNo = 0) THEN
StepNo = 1;
END_IF;
(* there's a shortcut unity operation for resetting this array to zeroes which is faster, but I can't remember it off the top of my head... *)
ActiveStepArray := BlankStepArray;
IF stepNo > 0 THEN
IF StepComplete[stepNo] THEN
stepNo := stepNo +1;
END_IF;
ActiveStepArray[stepNo] := true;
END_IF;
Then in other code sections you can put...
IF ActiveStep[1] THEN
(* Do something *)
StepComplete[1] := true;
END_IF;
IF ActiveStep[2] THEN
(* Do Something *)
StepComplete[2] := true;
END_IF;
(* etc *)
The nice thing about this approach is that you can actually put all of the state machine code (including jumps, resets etc) into a DFB, test it and then shelve it, and then just use the active step, step complete, and any other inputs you require.
Your code is still always going to execute an entire section of logic, but if you really want to avoid that then you'll have to use a lot of IF statements, which will impede readability.
Hope that helps.
Why not use SFC it makes your live easier in many cases, since it is state machine language itself. Do subprogram, wait condition do another .. rince and repeat. :)
Don't hang just for ST, the other IEC languages are better in some other tasks and keep thing as clear as possible. There should be not so much "this is my cake" mentality on the industrial PLC programming circles as it is on the many other programming fields, since application timeline can be 40 years and you left the firm 20 years ago to better job and programs are almost always location/customer or atleast hardware specific.
http://www.automation.com/pdf_articles/IEC_Programming_Thayer_L.pdf