Build a GameCreating Chess

7  The Computer

Goal

By the end of this chapter, the other Side thinks for itself. The Computer answers your Moves at the Strength you chose, and its Piece glides across the Board. Undo takes your last Turn back.

The game as it is at the end of this chapter. Click the game to play.

If your game and this chapter part ways, here is the chapter’s finished project. Open it and compare, or start Chapter 8 from it.

Chess, Chapter 7 finishedZip of a Myth project · 11.8 MB

To open it, right-click the downloaded file, choose Extract All... and then Extract. Start Myth Engine, choose File › Open Project... and pick the .mythproj file in the new folder. CREDITS.md and the licenses folder beside it come with the game.

7.1 The Idea

Play your game from Chapter 6. Move a White Pawn, and then walk round the table and move a Black one. Every Move on the Board is yours, both Sides. The chair across from you is empty.

This chapter fills it, and the other Side becomes the Computer. It’s the one part of your game that isn’t built from blocks. A chess program called Stockfish chooses its Moves. Stockfish comes into your game as a Library, a file of code your game carries inside it. Everything else is still the Logic you built, every rule that judges the Computer’s Moves and yours.

Here’s the real problem. You can’t ask Stockfish a question and stand still until it answers. Your game would freeze while it thinks. So the game asks the way you’d post a letter. It sends the question and goes on with its life, and the answer comes back later as a message of its own, computerMoveChosen. In between, the sign on the shop door from Chapter 4 says Computer’s Turn. The Board takes no clicks.

When the answer arrives, the Computer’s Piece doesn’t jump. It glides to its new Square in a little over a third of a second, and that glide is a slide.

Two promises get kept here. Chapter 6’s Strength starts to matter, at last. And a new button, Undo, takes your last Turn back, with the Computer’s reply to it.

7.2 The Plan

Here’s how the pieces work together. Read each line from left to right, once now for the shape, and again after the Computer plays.

  • A Turn goes on -> Look For Game End sends gameContinues -> Make Computer Move asks whether it’s the Computer’s Turn.
  • It is -> Ask The Computer turns the sign to Computer’s Turn and asks Stockfish.
  • Stockfish answers -> computerMoveChosen -> Make Computer Move checks the Move with Find Legal Moves.
  • The Move is legal -> Plan The Slide -> slideStarted.
  • The slide starts -> Slide Piece glides the Moving Piece, and Show Piece and Square Marks hide what it carries.
  • The slide lands -> pieceLanded -> Make Computer Move makes the Move with Make Move -> moveMade -> Start Turn writes it in the Move History.
  • No answer in time -> Mark Computer Unavailable -> the Retry button shows.
  • Undo is pressed -> Undo -> Take Back Moves starts the game again and makes every Move it keeps.

7.3 Set Up

Set upWhat this chapter adds
GAME SETTINGS > General > Game State
Available Game StatesPlaying, Promotion, Game Over, Computer's Turn, Computer Unavailable
SCENE Chess Table: PLACE THESE
ObjectXY
Undo Button-26040
with Text / UI > Text = Undo (Edit Object Locally)
Moving Piece1.8756.25hidden
Moving Piece1.8756.25hidden
with Per Instance Variables > Slide = Rook
with Per Instance Variables > Says When Landed = No
Unavailable Message070hidden
Retry Button040hidden
with Z-Index = 25
with UI Interaction > Group = Computer Unavailable (Edit Object Locally)
with Text / UI > Text = Retry (Edit Object Locally)

Two Game States join the list, Computer’s Turn and Computer Unavailable, and they go after Game Over, as the page’s passage on the Set up card says.

Each line under PLACE THESE waits for a part of this chapter, so each part sends you back here. The Moving Piece and the Unavailable Message are new Objects. Undo Button is a variant of Tool Button, and Retry Button a variant of Panel Button. The two Moving Piece lines are no copy slip: one carries a Piece, and the other a Rook when the Computer castles. Each button’s variant adds its own Logic, as Flip Button did in Chapter 6.

7.4 The Computer’s Tables

The Computer needs tables.

7.4.1 Strengths

Data StructureStrengths Entry

One row of the "Strengths" Data Table, which follows it. How the Computer plays at each Strength, one row per Strength button of the New Game panel (the row name is the button's word). skillLevel: Stockfish's Skill Level, from 0 (weakest) to 20 (strongest). thinkingSeconds: how long Stockfish thinks about each Move, in seconds.

skillLevelNumberdefault 0
thinkingSecondsNumberdefault 0
Data TableStrengthsData Structure: Strengths Entry
Row 0Gentle
skillLevel0
thinkingSeconds0.2
Row 1Casual
skillLevel4
thinkingSeconds0.35
Row 2Club
skillLevel8
thinkingSeconds0.5
Row 3Strong
skillLevel14
thinkingSeconds0.8
Row 4Expert
skillLevel20
thinkingSeconds1.2

Strengths has a row for each Strength on the New Game panel, by the same names. Its skillLevel is how well Stockfish plays, from 0 up to 20. Its thinkingSeconds is how long it thinks. Gentle thinks for 0.2 seconds, a blink, and Expert takes 1.2 seconds, long enough to notice.

7.4.2 Chosen Moves

Data StructureChosen Moves Entry

One row of the "Chosen Moves" Data Table, which follows it. The Move the Computer chose, written by the Stockfish Bridge just before it says "computerMoveChosen". from and to: the Squares the Piece moves from and to (a1 to h8). landingKind: the Kind of the Piece once it has landed: its own Kind, or, when the Move promotes a Pawn, the Kind the Pawn becomes (Queen, Rook, Bishop, or Knight).

fromTextdefault (empty)
toTextdefault (empty)
landingKindTextdefault (empty)
Data TableChosen MovesData Structure: Chosen Moves Entry
Row 0Computer
from
to
landingKind

Chosen Moves has one row, Computer, with three empty Text columns. Make those fields in Chosen Moves Entry, and the table gets its columns from them. Stockfish writes its answer here: from, to, and landingKind, the Kind the Piece will be once it lands. That last one matters only for a Pawn that promotes. It becomes whatever Kind Stockfish named.

7.4.3 Words

Data TableWordsData Structure: Words EntryAddDelete
Row 0Your Move
textYour move
Row 1Check
textCheck
Row 2Promotion
textPromotion: choose a Piece
Row 3Win By Checkmate
textYou win · Checkmate
Row 4Loss By Checkmate
textYou lose · Checkmate
Row 5Draw By Stalemate
textDraw · Stalemate
Row 6Draw By Insufficient Material
textDraw · Insufficient material
Row 7Draw By Fifty Move Rule
textDraw · Fifty-move rule
Row 8Draw By Threefold Repetition
textDraw · Threefold repetition
Row 9Thinking
textThinking…
Row 10Disconnected
textOpponent disconnected

Two rows join Words. Thinking… ends with three dots that are one character, not three periods, so copy it from the card. Disconnected says Opponent disconnected.

7.4.4 Stockfish Bridge

LibraryStockfish Bridge
SOURCEfrom a file
Import .js...stockfish-bridge.js, from the zip
Size781.9 KB
ADVANCED WIRING AND LOAD ORDER
Alias (Lib.Ext....)stockfishBridge
Global NameStockfishBridge
TypeClassic Build

The Stockfish Bridge is the Library. It’s Stockfish, and a small bridge around it. The bridge turns your Position table and Board State into words Stockfish reads, and asks for a Move at the Strength you chose. It writes the answer into Chosen Moves and sends computerMoveChosen.

A Library card shows how to add it, from the download to the Alias. The Alias is the name your Logic calls it by, so type stockfishBridge exactly. Once the file is in, Myth shows its size. It’s the card’s Size, 781.9 KB, when you have the right file.

Myth reads a Library’s code when you import it, and a yellow note lists what that code could do. Keep a Library only if you trust it, the note says. That’s good advice. This one names a few web addresses in Stockfish’s credits, and thinks in the background on your computer. The game never needs the internet to play.

The zip has two more things beside the Library’s file, CREDITS.md and a licenses folder. They’re Stockfish’s. Copy them into the folder that holds your project’s .mythproj file, the one you pick in File › Open Project…, and keep them there.

7.5 Every Move, Written Down

Before the Computer plays, the game learns to keep a record. Undo will need it later in this chapter, and so will the Computer’s own Moves.

7.5.1 Move History

Data StructureMove History Entry

One row of the "Move History" Data Table, which follows it. Every Move of the game so far, in the order they were made, one row per Move (the first Move is row 0; each row is named by its number). from and to: the Squares the Piece moved from and to (a1 to h8). landingKind: the Kind of the Piece once it had landed: its own Kind, or, for a Promotion, the Kind the Pawn became. The number of rows is the number of Moves made. Undo takes rows off the end and plays the rest again. The table starts empty.

fromTextdefault (empty)
toTextdefault (empty)
landingKindTextdefault (empty)
Data TableMove HistoryData Structure: Move History Entry

Move History starts with no rows at all. Each Move adds one: its from and to, and the Kind that landed.

7.5.2 Record Move

FunctionRecord Move

Writes the Move just made (Board State's lastFrom and lastTo) at the end of the Move History table, with the Kind the Piece landed as. gameRules: the Game Rules Object, whose Board State holds the last Move.

PARAMETERS
NameTypeStarts at
gameRulesObjectStructural
Required Components
Slot NameboardState
Component TypeData Structure
Required SchemaBoard State
ACTIONS
1Declare Variable
Type
Text
Name
fromSquare
2Declare Variable
Type
Text
Name
toSquare
3Declare Variable
Name
lastRow
Value
0
4Change Variable
Variable
fromSquare
Value
gameRules.boardState.lastFrom
5Change Variable
Variable
toSquare
Value
gameRules.boardState.lastTo
6Control Data Row
Action Name
addedRow
Table
Move History
Row
dataCount('Move History')
7Change Variable
Variable
lastRow
Value
dataCount('Move History') - 1
8Set Data Cell
Table
Move History
Row
lastRow
Column
"from"
Value
fromSquare
9Set Data Cell
Table
Move History
Row
lastRow
Column
"to"
Value
toSquare
10Set Data Cell
Table
Move History
Row
lastRow
Column
"landingKind"
Value
data('Position', toSquare, 'kind')

Record Move writes the Move that was made last at the bottom of the Move History. Board State already knows it, in lastFrom and lastTo. It adds a row at the end, as Record Position did in Chapter 5, and fills it in. Its Control Data Row has no Operation line, because that stays as it starts, on adding the row.

7.5.3 Pass The Turn

FunctionPass The Turn

Gives the Turn to the other Side (the Sides table's opponent column). gameRules: the Game Rules Object, whose Board State holds whose Turn it is (sideToMove).

PARAMETERS
NameTypeStarts at
gameRulesObjectStructural
Required Components
Slot NameboardState
Component TypeData Structure
Required SchemaBoard State
ACTIONS
1Declare Variable
Type
Text
Name
side
2Change Variable
Variable
side
Value
gameRules.boardState.sideToMove
3Change Component Value
Component Value
gameRules.boardState.sideToMove
Value
data('Sides', side, 'opponent')

Pass The Turn does the work you’ve met before, in Start Turn. They give the Turn to the other Side. Undo needs them too, so now they’re a Function of their own.

7.5.4 Start The Turn

FunctionStart The Turn

Starts the Turn of the Side to move, in the position on the Board: marks a King in Check and sets the status line (Look For Check), then tells the Game Rules "turnStarted" (Look For Game End asks whether the game is over; if it goes on, Make Computer Move asks whether it is the Computer's Turn). gameRules: the Game Rules Object.

PARAMETERS
NameTypeStarts at
gameRulesObjectStructural
Required Components
Slot NameboardState
Component TypeData Structure
Required SchemaBoard State
ACTIONS
1Look For CheckFunction
gameRules
gameRules
2Trigger Custom Event on Object
Applies to
gameRules
Custom Event
turnStarted

Start The Turn holds the two steps Start Turn always began a Turn with. Start Turn and Undo will both start Turns now, so those steps get a home that both can call.

7.5.5 Start Turn

Logic ComponentStart TurnAttach to: Game RulesAddDelete

Starts each Turn: the first one (White's) when the game begins, and the next one after every Move, which it first writes down in the Move History (Record Move) before giving the Turn to the other Side (Pass The Turn). Each Turn starts with Start The Turn: it asks whether the Side to move is in Check, then tells the Game Rules that the Turn has started ("turnStarted").

Attach toAny Object
DATA STRUCTURES
Board Stateself.boardState
When Created
WhenCreate
1Look For CheckFunction
gameRules
self
2Trigger Custom Event on Object
Custom Event
turnStarted
1Start The TurnFunction
gameRules
self
2Trigger Custom Event
Custom Event
positionChanged
On Move Made
WhenmoveMadeCustom Event
1Declare Variable
Type
Text
Name
side
2Change Variable
Variable
side
Value
self.boardState.sideToMove
3Change Component Value
Component Value
self.boardState.sideToMove
Value
data('Sides', side, 'opponent')
1Record MoveFunction
gameRules
self
2Pass The TurnFunction
gameRules
self
3Change Component Value
Component Value
self.boardState.selected
Value
''
4Clear TargetsFunction
6Look For CheckFunction
gameRules
self
7Trigger Custom Event on Object
Custom Event
turnStarted
5Start The TurnFunction
gameRules
self

Start Turn gets shorter. Its side Declare goes, with the steps that moved into the new Functions. When Created calls Start The Turn, then sends positionChanged as before. On Move Made writes the Move down first, with Record Move, and then it passes the Turn, clears the selection and the dots, and starts the next Turn.

The struck steps keep their old numbers, so some numbers show twice. Delete the struck ones first. In When Created, Start The Turn goes in front of the old step that sends positionChanged. In On Move Made, Record Move and Pass The Turn go in front of the old step that clears the selection. Start The Turn goes last, after Clear Targets.

To put a step in front of an old one, add it apart from the line. Use the round handles to join it after the block it follows, as in Chapter 4. To put it first, start from the Mode’s bottom handle.

Run the game. It plays the way it did, and the Move History fills up where you can’t see it.

7.6 Asking the Computer

Now the question, and the answer.

7.6.1 Ask The Computer

FunctionAsk The Computer

Asks the Computer for its Move: the Board waits (Game State Computer's Turn), the status line says the Computer is thinking, and the Stockfish Bridge (a Library of code) asks Stockfish for a Move at the Strength in Board State; it answers with "computerMoveChosen". The named timer answerWait rings once if no answer has come in time: the Strength's thinking time plus spareSeconds. gameRules: the Game Rules Object. spareSeconds: how much longer than its thinking time the Computer may take to answer, starting Stockfish included.

PARAMETERS
NameTypeStarts at
gameRulesObjectStructural
Required Components
Slot NameboardState
Component TypeData Structure
Required SchemaBoard State
spareSecondsNumber20
ACTIONS
1Declare Variable
Name
waitSeconds
Value
0
2Set Game State
Game State
Computer's Turn
3Change Variable
Variable
$status
Value
data('Words', 'Thinking', 'text')
4Run Code (JS)
Applies to
gameRules
Java Script
lib.ext.stockfishBridge.chooseComputerMove(api, ctx.self);
5Change Variable
Variable
waitSeconds
Value
data('Strengths', gameRules.boardState.strength, 'thinkingSeconds')
6Change Variable
Variable
waitSeconds
Operator
+=
Value
spareSeconds
7Start Recurring Timer
Applies to
gameRules
Timer Name
"answerWait"
Repeat Every (s)
waitSeconds
Ring Once
true

Ask The Computer puts the question. First, Set Game State turns the sign to Computer’s Turn, so the Board stops answering, and $status says Thinking…. One step of code, Run Code (JS), asks the Library for a Move. Type it exactly as the card has it. It needs Advanced Mode. It’s one of only two lines of code you’ll write in this game. The other comes in Chapter 8, and it asks the Library for a Hint.

The last three steps start a clock. What if Stockfish never answers? Steps 5 and 6 add up waitSeconds: this Strength’s thinking time, and spareSeconds more, 20 seconds of patience. The second one adds on, with +=. Start Recurring Timer starts a timer named answerWait on the Game Rules. Its Ring Once is true. It rings one time, and stops.

7.6.2 Mark Computer Unavailable

FunctionMark Computer Unavailable

Gives up waiting for the Computer: the game keeps its position and waits for the Player to press Retry (Game State Computer Unavailable, which shows the message and its Retry button), and the status line says the opponent is disconnected. gameRules: the Game Rules Object.

PARAMETERS
NameTypeStarts at
gameRulesObjectStructural
Required Components
Slot NameboardState
Component TypeData Structure
Required SchemaBoard State
ACTIONS
1Stop Recurring Timer
Applies to
gameRules
Timer Name
"answerWait"
2Set Game State
Game State
Computer Unavailable
3Change Variable
Variable
$status
Value
data('Words', 'Disconnected', 'text')

Mark Computer Unavailable is what happens when the clock rings before any answer comes.

7.6.3 Slides and Plan The Slide

Data StructureSlides Entry

One row of the "Slides" Data Table, which follows it. Where the Pieces of the Computer's Move slide, written just before they slide (Plan The Slide) and read by the Moving Pieces (each placement follows one row) and by the Pieces, which show nothing on a Square a slide starts from. Row Piece: the Piece that moves. Row Rook: the Rook, when the Move is a castling (empty otherwise). from and to: the Squares it slides from and to (a1 to h8).

fromTextdefault (empty)
toTextdefault (empty)
Data TableSlidesData Structure: Slides Entry
Row 0Piece
from
to
Row 1Rook
from
to

Slides says where each Piece of the Computer’s Move will glide. Row Piece is the Piece that moves, and row Rook is for a castling, when the Rook moves too.

FunctionPlan The Slide

Writes where the Pieces of one Move slide, before the Move is made (the Slides table): the Piece from its Square to the new one, and, when the Move is a castling, the Rook too, as the Castling table says. from and to: the Squares the Piece moves from and to.

PARAMETERS
fromText
toText
ACTIONS
1Declare Variable
Type
Text
Name
kind
2Declare Variable
Type
Text
Name
rookFrom
3Declare Variable
Type
Text
Name
rookTo
4Change Variable
Variable
kind
Value
data('Position', from, 'kind')
5Reset Data Table
Table
Slides
6Set Data Cell
Table
Slides
Row
"Piece"
Column
'from'
Value
from
7Set Data Cell
Table
Slides
Row
"Piece"
Column
'to'
Value
to
8RepeatdataCount('Castling')times
Each time
9Ifkind == "King" && data('Castling', local.index, 'kingFrom') == from && data('Castling', local.index, 'kingTo') == to
Then
10Change Variable
Variable
rookFrom
Value
data('Castling', local.index, 'rookFrom')
11Change Variable
Variable
rookTo
Value
data('Castling', local.index, 'rookTo')
12Set Data Cell
Table
Slides
Row
"Rook"
Column
'from'
Value
rookFrom
13Set Data Cell
Table
Slides
Row
"Rook"
Column
'to'
Value
rookTo

Plan The Slide fills it in before the Move is made. It empties the table, and writes the Move’s two Squares into row Piece. Next it walks the Castling table from Chapter 4. Is the Piece a King, going from a row’s kingFrom to its kingTo? That’s a castling, and the Rook’s two Squares go into row Rook.

7.6.4 Make Computer Move

This is the chapter’s biggest card, with five Events. Take them in order, and they tell the whole story of a Computer Turn.

Make Make Computer Move Data first, then add it beside Board State on the canvas’s Data Structures card. Its slot name is makeComputerMoveData. It keeps the Move while the answer is checked and the Piece slides.

Data StructureMake Computer Move Data

What Make Computer Move remembers on the Game Rules about the Computer's Move. fromSquare and toSquare: the Move's Squares. landingKind: the Kind a Pawn becomes, or empty.

fromSquareTextdefault (empty)
toSquareTextdefault (empty)
landingKindTextdefault (empty)
Logic ComponentMake Computer MoveAttach to: Game Rules

Plays the Computer's Turns. When a Turn goes on ("gameContinues", from Look For Game End) and the Side to move is the Player's opponent (the Sides table), it asks the Computer for a Move (Ask The Computer: the Board waits in Computer's Turn while the Stockfish Bridge asks Stockfish at the Strength in Board State). When Stockfish answers ("computerMoveChosen"; the Move is in the Chosen Moves table) and it is still the Computer's Turn and the Move is a Legal Move, the Move slides first (Plan The Slide fills the Slides table; everyone hears "slideStarted"). When it has landed ("pieceLanded", from the Moving Piece), it is made if it is still the Computer's Turn, the way the Player's Moves are made: Make Move, the Kind it lands as (a promoted Pawn becomes the Kind Stockfish named), then "moveMade" (Start Turn starts the Player's Turn) and "positionChanged". When Stockfish gives no Move, or one that is not legal, or does not answer within its thinking time and spareSeconds more (the answerWait timer), the position stays and the Computer is marked unavailable (Mark Computer Unavailable) until the Player presses Retry ("retryPressed"), which asks again. spareSeconds: how much longer than its thinking time the Computer may take to answer, starting Stockfish included. A Player whose device asks for less motion (the system setting "reduce motion", the Myth Global prefersReducedMotion) sees the Move made at once, with no slide.

Attach toAny Object
DATA STRUCTURES
Board Stateself.boardState
Make Computer Move Dataself.makeComputerMoveData
SHARED VARIABLES
NameTypeKindStarting Value
spareSecondsNumberConstant20
On Game Continues
WhengameContinuesCustom Event
1Ifself.boardState.sideToMove == data('Sides', self.boardState.playerSide, 'opponent')
Then
2Ask The ComputerFunction
gameRules
self
spareSeconds
@self.spareSeconds
On Computer Move Chosen
WhencomputerMoveChosenCustom Event
1Check Game State
Action Name
isThinking
Game State
Computer's Turn
2IfisThinking.value == true
Then
3Stop Recurring Timer
Timer Name
"answerWait"
4Change Component Value
Component Value
self.makeComputerMoveData.fromSquare
Value
data('Chosen Moves', 'Computer', 'from')
5Change Component Value
Component Value
self.makeComputerMoveData.toSquare
Value
data('Chosen Moves', 'Computer', 'to')
6Find Legal MovesFunction
from
self.makeComputerMoveData.fromSquare
enPassantSquare
self.boardState.enPassantSquare
7Ifdata('Targets', self.makeComputerMoveData.toSquare, 'reachable') == true
Then
8If$prefersReducedMotion == 1
Then
9Trigger Custom Event on Object
Custom Event
pieceLanded
10Otherwise
11Plan The SlideFunction
from
self.makeComputerMoveData.fromSquare
to
self.makeComputerMoveData.toSquare
12Trigger Custom Event
Custom Event
slideStarted
13Otherwise
14Clear TargetsFunction
15Mark Computer UnavailableFunction
gameRules
self
On Piece Landed
WhenpieceLandedCustom Event
1Check Game State
Action Name
isLanding
Game State
Computer's Turn
2IfisLanding.value == true
Then
3Change Component Value
Component Value
self.makeComputerMoveData.fromSquare
Value
data('Chosen Moves', 'Computer', 'from')
4Change Component Value
Component Value
self.makeComputerMoveData.toSquare
Value
data('Chosen Moves', 'Computer', 'to')
5Change Component Value
Component Value
self.makeComputerMoveData.landingKind
Value
data('Chosen Moves', 'Computer', 'landingKind')
6Set Game State
Game State
Playing
7Make MoveFunction
gameRules
self
from
self.makeComputerMoveData.fromSquare
to
self.makeComputerMoveData.toSquare
8Set Data Cell
Table
Position
Row
self.makeComputerMoveData.toSquare
Column
"kind"
Value
self.makeComputerMoveData.landingKind
9Trigger Custom Event on Object
Custom Event
moveMade
10Trigger Custom Event
Custom Event
positionChanged
On the Answer Wait Timer
WhenRecurring TimerTimer name: answerWait
1Check Game State
Action Name
isStillThinking
Game State
Computer's Turn
2IfisStillThinking.value == true
Then
3Mark Computer UnavailableFunction
gameRules
self
On Retry Pressed
WhenretryPressedCustom Event
1Check Game State
Action Name
isUnavailable
Game State
Computer Unavailable
2IfisUnavailable.value == true
Then
3Ask The ComputerFunction
gameRules
self
spareSeconds
@self.spareSeconds

On Game Continues comes first. It asks whether the Side to move is the Player’s opponent, the one the Sides table names. If it is, Ask The Computer puts the question. On your own Turn, nothing happens at all.

On Computer Move Chosen hears the answer, and its first two steps ask a question of their own. Check Game State asks whether the sign still says Computer’s Turn, and the If goes on only if it does. Why ask? An answer can come late, after you’ve pressed Undo, and a late answer counts for nothing.

It stops the clock and reads the Move from Chosen Moves. But it doesn’t take Stockfish’s word for it. Find Legal Moves marks Targets for that Piece, as it does for yours. Is the to Square reachable? Only then does the Move go ahead. A Move that isn’t legal, or no Move at all, clears the dots and marks the Computer unavailable.

Inside the legal branch, there’s one more question. The Global $prefersReducedMotion is one Myth Engine keeps for you. It’s 1 when your computer’s own settings ask for less motion, and then the Move lands at once, with no slide. Otherwise Plan The Slide fills Slides, and slideStarted goes out to everyone.

On Piece Landed makes the Move. It checks the sign once more, reads the Move again, and turns the sign back to Playing first. That’s Chapter 5’s lesson from Choose Promotion. A Move can end the game, and a Playing set after it would wake a finished game up again. Make Move comes next, with the Kind it lands as. Last come moveMade and positionChanged, as your own Moves send.

On the Answer Wait Timer is the clock ringing: if the Computer is still thinking, it’s marked unavailable. Its When bar is a Recurring Timer, and Events: the When bars shows how to give one its name. On Retry Pressed asks again, only while the Computer is unavailable.

Each Check Game State has its own Action Name and its own Game State in the list, and each If reads that name’s value. Its spareSeconds is a constant Number Shared Variable, as the card shows.

7.6.5 Look For Game End

Logic ComponentLook For Game EndAttach to: Game RulesAddDelete

Ends the game at the start of every Turn (Start Turn sends "turnStarted") when the Side to move has no Legal Move (Is Out Of Moves), when neither Side can give Checkmate (Is Material Insufficient), when the same position has come timesSeenForDraw times (Record Position, Is Position Repeated), or when fiftyMoveCountForDraw Moves in a row have had no Capture and no Pawn Move (the fifty-move rule; Make Move counts them). The status line shows the result (Show Result), and the game is over (Game State Game Over), so the Board no longer answers and the final position stays. Otherwise it tells the Game Rules "gameContinues", and the Turn goes on. timesSeenForDraw: 3, threefold repetition. fiftyMoveCountForDraw: 100, fifty Moves by each Side.

Attach toAny Object
DATA STRUCTURES
Board Stateself.boardState
SHARED VARIABLES
NameTypeKindStarting Value
timesSeenForDrawNumberConstant3
fiftyMoveCountForDrawNumberConstant100
On Turn Started
WhenturnStartedCustom Event
1Is Out Of MovesFunction
Action Name
outOfMoves
gameRules
self
2Is Material InsufficientFunction
Action Name
material
3Record PositionFunction
gameRules
self
4Is Position RepeatedFunction
Action Name
repetition
timesForDraw
@self.timesSeenForDraw
5IfoutOfMoves.value == true || material.value == true || repetition.value == true || self.boardState.fiftyMoveCount >= @self.fiftyMoveCountForDraw
Then
6Show ResultFunction
gameRules
self
isOutOfMoves
outOfMoves.value
isMaterialInsufficient
material.value
isRepeated
repetition.value
7Set Game State
Game State
Game Over
8Otherwise
9Trigger Custom Event on Object
Custom Event
gameContinues

Look For Game End gets an Else. When no ending is found, step 9 sends gameContinues, and Make Computer Move hears it. Add the Else to step 5’s If with Add Else. Add the Trigger through the Else’s Add Inside Else, and join it there.

7.6.6 Game Rules

ObjectGame RulesAddDelete
Data Structure
Data StructureBoard State
Data Structure
From LogicSelect and Move
Data StructureSelect and Move Data
Data Structure
From LogicChoose Promotion
Data StructureChoose Promotion Data
Data Structure
From LogicMake Computer Move
Data StructureMake Computer Move Data
Data Structure
From LogicUndo
Data StructureUndo Data
Logic
Select and Move
Start Turn
Choose Promotion
Look For Game End
Flip Board
New Game
Make Computer Move
Undo

Attach Make Computer Move to the Game Rules now. Undo’s line waits until Undo exists, later in this chapter.

You won’t see the Computer move yet, because its Piece needs something to carry it. Run the game now, and the words stay on Thinking…, with no Piece moving. That’s expected, because nothing says the Piece has landed yet. The next part does. Keep going.

7.7 The Slide

One Object carries the Computer’s Piece across the Board.

7.7.1 Moving Piece

ObjectMoving Piece
Transform
Bounding Box > SizeX 3.4765, Y 3.4765
Sprite
Scene Depth Draw Order12
SpriteCarved Walnut Pieces
Transform > SizeX 3.4765, Y 3.4765
Data Structure
From LogicSlide Piece
Data StructureSlide Piece Data
Logic
Slide Piece

The Moving Piece looks like any Piece, the same picture at the same size. But it stands on no Square, and its Scene Depth Draw Order is 12, so it’s drawn over the Pieces. It’s the Computer’s hand.

7.7.2 Slide Piece

Start this card at its end. Make the On Board Flipped Event first, with its two Modes, Stay Hidden and Land At Once. Step 14 and On Position Changed’s step 3 pick them from lists with Switch Mode, and a list holds only what’s already there. Modes shows how to make the pair.

Make Slide Piece Data before the Logic. Add it to the canvas’s Data Structures card with slidePieceData as its slot. Those fields keep the Piece’s Kind, Side and Board direction through the slide.

Data StructureSlide Piece Data

What Slide Piece remembers on the Moving Piece while it slides. isFlipped: whether the Board is drawn turned over. kind and side: the Piece it shows.

isFlippedBooleandefault false
kindTextdefault (empty)
sideTextdefault (empty)
Logic ComponentSlide PieceAttach to: Moving Piece

Slides one Piece of the Computer's Move across the Board before the Move is made. When the Game Rules say "slideStarted" (they are its Other), it reads its row of the Slides table: if the row names a Square, it shows the Piece standing there and glides from that Square to the row's other Square in slideSeconds, starting and ending slowly. The Moving Piece that says so (saysWhenLanded) then tells the Game Rules "pieceLanded", and they make the Move; the next "positionChanged" hides it again. While it slides, a Board turned over or back ("boardFlipped") ends the slide at once (Event Logic Land At Once): the Move is made, drawn the new way round; between slides a turned Board changes nothing here (Stay Hidden). slide: which row of the Slides table it follows (Piece, or Rook for a castling). slideSeconds: how long the slide takes. saysWhenLanded: true for the one Moving Piece that says when the slide is over (a King and its Rook land together). squareMeters, boardLeft, and boardBottom: where the Squares are (as for Place On Board).

Attach toAny Object
DATA STRUCTURES
Slide Piece Dataself.slidePieceData
SHARED VARIABLES
NameTypeKindStarting Value
slideSecondsNumberConstant0.36
squareMetersNumberConstant3.75
boardLeftNumberConstant0
boardBottomNumberConstant4.375
PER INSTANCE VARIABLES
NameTypeStarting Value
slideTextPiece
saysWhenLandedBooleanYes
On Slide Started
WhenslideStartedCustom Event
1Declare Variable
Type
Text
Name
toSquare
2Declare Variable
Type
Text
Name
fromSquare
3Change Variable
Variable
fromSquare
Value
data('Slides', self.slide, 'from')
4Change Variable
Variable
toSquare
Value
data('Slides', self.slide, 'to')
5IffromSquare != ""
Then
6Change Component Value
Component Value
self.slidePieceData.isFlipped
Value
other.boardState.isFlipped
7Square PositionFunction
Action Name
startSquare
square
fromSquare
isFlipped
self.slidePieceData.isFlipped
squareMeters
@self.squareMeters
boardLeft
@self.boardLeft
boardBottom
@self.boardBottom
8Square PositionFunction
Action Name
endSquare
square
toSquare
isFlipped
self.slidePieceData.isFlipped
squareMeters
@self.squareMeters
boardLeft
@self.boardLeft
boardBottom
@self.boardBottom
9Change Component Value
Component Value
self.slidePieceData.kind
Value
data('Position', fromSquare, 'kind')
10Change Component Value
Component Value
self.slidePieceData.side
Value
data('Position', fromSquare, 'side')
11Set Frame
Frame
data('Kinds', self.slidePieceData.kind, self.slidePieceData.side)
12Set Position
X
startSquare.x
Y
startSquare.y
13Set Visible
Visible
Yes
14Switch Mode
Event
On Board Flipped
Mode
Land At Once
15Tween
Value
self.transform.position.x
Target
endSquare.x
Duration
@self.slideSeconds
Ease
Sine in Out
16Tween
Value
self.transform.position.y
Target
endSquare.y
Duration
@self.slideSeconds
Ease
Sine in Out
17Otherwise
18Return
19Ifself.saysWhenLanded == true
Then
20Start Recurring Timer
Timer Name
"landing"
Repeat Every (s)
@self.slideSeconds
Ring Once
Yes
On the Landing Timer
WhenRecurring TimerTimer name: landing
1Trigger Custom Event
Custom Event
pieceLanded
On Position Changed
WhenpositionChangedCustom Event
1Set Visible
Visible
No
2Stop Recurring Timer
Timer Name
"landing"
3Switch Mode
Event
On Board Flipped
Mode
Stay Hidden
On Board Flipped
WhenboardFlippedCustom Event
ModeStay Hidden (Starting Mode)
(no Actions)
On Board Flipped
WhenboardFlippedCustom Event
ModeLand At Once
1Ifself.saysWhenLanded == true
Then
2Trigger Custom Event
Custom Event
pieceLanded

Slide Piece hears slideStarted, and reads its own row of Slides, Piece or Rook, as its slide Per Instance Variable says. An empty Rook row means no castling, and Return ends it there.

Otherwise, it gets ready. Square Position tells it where both Squares are drawn now, turned or not. Set Frame gives it the picture of the Piece on the from Square, and Set Position and Set Visible put it there, in plain view. Two Tween steps glide it, one across and one up or down. Type self.transform.position.x into the first one’s Value box, and self.transform.position.y into the second’s. Each moves its value to the Target over slideSeconds, 0.36 seconds, its Duration. The Ease Sine in Out starts slowly and ends slowly, the way a hand sets a Piece down.

The Moving Piece whose saysWhenLanded is true starts a timer, landing, as long as the slide. When it rings, pieceLanded goes to the Game Rules. A King and its Rook land together, so only one of them says so.

When positionChanged comes, the Moving Piece hides again and stops its timer.

The two On Board Flipped Events are one Event with two ways to answer, two Modes. Stay Hidden does nothing. Land At Once makes the Move land right then. Why? Press Flip mid-slide, and the Piece would glide along a line on a Board that isn’t there anymore. Switch Mode switches between them. It runs at the start of the slide, and again when the Piece hides.

Its Other is the Game Rules, which sends slideStarted. Its Shared Variables include Place On Board’s three Numbers again.

Now go to the Set up card and place the two Moving Pieces, hidden. The second sets slide to Rook, and saysWhenLanded to Off. Both are in the placement’s Per Instance Variables. A Boolean there is a switch, and Off is the card’s No.

7.7.3 Show Piece and Square Marks

Logic ComponentShow PieceAttach to: PieceAddDelete

Shows the Piece that stands on this Piece Object's Square: once the Board is laid out (Lay Out The Board sends "boardLaidOut"), and again after every Move (the Game Rules send "positionChanged"). While the Computer's Move slides ("slideStarted"), a Piece on a Square a slide starts from (the Slides table) shows nothing, because a Moving Piece carries it.

Attach toAny Object
DATA STRUCTURES
Square Infoself.squareInfo
On Board Laid Out
WhenboardLaidOutCustom Event
1Show Piece On SquareFunction
piece
self
On Position Changed
WhenpositionChangedCustom Event
1Show Piece On SquareFunction
piece
self
On Slide Started
WhenslideStartedCustom Event
1IfdataFind('Slides', 'from', self.squareInfo.name) != (-1)
Then
2Set Alpha
Alpha
0

While a Piece slides, the one on its starting Square must vanish, or you’d see it twice. The dataFind in its If looks down the from column of Slides for this Square’s name. It gives -1 when the name isn’t there. Any other answer means a slide starts here, and Set Alpha hides the Piece.

Logic ComponentSquare MarksAttach to: SquareAddDelete

Shows the highlight on this Square after every change (the Game Rules send "positionChanged" and are its Other): a tint when it was part of the last Move, when its Piece is selected, or when its King is in Check (the most important one shows). The colors, and how strongly each shows, are its Parameters. While the Computer's Move slides ("slideStarted"), no highlight is shown.

Attach toAny Object
DATA STRUCTURES
Square Infoself.squareInfo
SHARED VARIABLES
NameTypeKindStarting Value
selectedColorColorConstant#f4d273
selectedAlphaNumberConstant0.44
lastMoveColorColorConstant#e9c44f
lastMoveAlphaNumberConstant0.32
checkColorColorConstant#cd493f
checkAlphaNumberConstant0.66
On Position Changed
WhenpositionChangedCustom Event
1Set Alpha
Alpha
0
2Ifself.squareInfo.name == other.boardState.lastFrom || self.squareInfo.name == other.boardState.lastTo
Then
3Change Sprite Tint Property
Value
@self.lastMoveColor
4Set Alpha
Alpha
@self.lastMoveAlpha
5Ifself.squareInfo.name == other.boardState.selected
Then
6Change Sprite Tint Property
Value
@self.selectedColor
7Set Alpha
Alpha
@self.selectedAlpha
8Ifself.squareInfo.name == other.boardState.checkSquare
Then
9Change Sprite Tint Property
Value
@self.checkColor
10Set Alpha
Alpha
@self.checkAlpha
On Slide Started
WhenslideStartedCustom Event
1Set Alpha
Alpha
0

Square Marks hides its color for the slide too. The Move sets it again when it lands.

Run the game. Play e2 to e4.

For a moment, the words under the Board say Thinking…. Then a Black Piece lifts from its Square and glides to a new one, slow at the start and slow at the end. The words go back to Your move.

The chair across the table isn’t empty anymore. Which Move it chose is up to Stockfish, and it may choose another next time.

7.8 When the Computer Can’t Answer

You may never see this part. It shows only if Stockfish fails to start or to answer.

7.8.1 Report Retry

Logic ComponentReport Retry

What the Retry button does: it tells whoever listens (the Game Rules) with "retryPressed".

Attach toAny Object
On Hud Activated
WhenUI Activated
1Trigger Custom Event
Custom Event
retryPressed

Report Retry is one more button’s Logic Component. UI Activated starts it. It sends retryPressed, as Report Flip sends its message.

7.8.2 Unavailable Message

ObjectUnavailable Message
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorCenter
Presentation > Render LayerUI
Bounding Box > SizeX 420, Y 150
UI Interaction
Element TypeText
GroupComputer Unavailable
Sprite
Scene Depth Draw Order24
SpriteSquare Highlight
Tint#EFE6CF
Transform > SizeX 420, Y 150
Text / UI
TextOpponent unavailable.
Font Size22
EmphasisSemibold
Color#503A2B
AlignmentCenter
Transform > PositionX 0, Y 32
Logic
Show Unavailable Message

The Unavailable Message is a cream card in the UI Group Computer Unavailable. Nobody presses it, so its Element Type is Text, as on the New Game Panel. Its own words say Opponent unavailable., while the Words row you added at the start of this chapter says Opponent disconnected. That’s no slip. Both show at once, the short line under the Board and this card above Retry.

Logic ComponentShow Unavailable MessageAttach to: Unavailable Message

Shows the message "Opponent unavailable." and its Retry button (the UI Group "Computer Unavailable") exactly while the Game State is Computer Unavailable, and hides them otherwise.

Attach toAny Object
On Game State Changed
WhenGame State Changed
1Check Game State
Action Name
isUnavailable
Game State
Computer Unavailable
2IfisUnavailable.value == true
Then
3Set UI Group Visibility
UI Group
"Computer Unavailable"
4Otherwise
5Set UI Group Visibility
UI Group
"Computer Unavailable"
Visible
No

Show Unavailable Message hears Game State Changed. That Event comes whenever the sign turns, so the message and Retry come and go with the sign.

The message’s Tint is on its Object card, the cream #EFE6CF. Now make Retry Button, from Panel Button. It adds Report Retry and keeps the base Object’s tan.

Object variantRetry ButtonVariant of: Panel Button
Logic
Report Retry

Place the message from the Set up card, hidden, then Retry Button, with Retry for its words. Its Group line puts that placement in the message’s group.

7.9 Undo

Undo needs a new button, and an idea. How do you take a Move back, when Board State doesn’t remember the Board before it? Undo doesn’t run the game backward. It sets the Board up fresh, and makes every Move still in the Move History again, quickly, where you can’t see. That’s why Record Move came first.

7.9.1 Go Back To The Start

FunctionGo Back To The Start

Puts the game back as it is when a game starts: the starting position, every castling allowed again, no position seen yet, and nothing marked (the tables as they were made), and Board State as a game starts: White to move, no en passant Square, no Moves counted for the fifty-move rule, no last Move, and nothing selected. gameRules: the Game Rules Object.

PARAMETERS
NameTypeStarts at
gameRulesObjectStructural
Required Components
Slot NameboardState
Component TypeData Structure
Required SchemaBoard State
ACTIONS
1Reset Data Table
Table
Position
2Reset Data Table
Table
Castling
3Reset Data Table
Table
Position History
4Clear TargetsFunction
5Change Component Value
Component Value
gameRules.boardState.sideToMove
Value
'White'
6Change Component Value
Component Value
gameRules.boardState.enPassantSquare
Value
''
7Change Component Value
Component Value
gameRules.boardState.fiftyMoveCount
Value
0
8Change Component Value
Component Value
gameRules.boardState.lastFrom
Value
''
9Change Component Value
Component Value
gameRules.boardState.lastTo
Value
''
10Change Component Value
Component Value
gameRules.boardState.selected
Value
''

Go Back To The Start sets everything as a new game has it, the tables and Board State alike. Reset Data Table, which emptied Slides in Plan The Slide, puts each table back the way you made it, every row as it was.

7.9.2 Take Back Moves

FunctionTake Back Moves

Takes back every Move after the first movesKept Moves: they leave the Move History, the game goes back to its start (Go Back To The Start), and the Moves kept are made again in order, as the game made them, with the position of each Turn recorded first (as at the start of every Turn) so threefold repetition still counts them. Castling, en passant, Promotion, and the fifty-move count come back as they were, because every Move is made with Make Move. gameRules: the Game Rules Object. movesKept: how many Moves, from the first, stay made.

PARAMETERS
NameTypeStarts at
gameRulesObjectStructural
Required Components
Slot NameboardState
Component TypeData Structure
Required SchemaBoard State
movesKeptNumber0
ACTIONS
1Declare Variable
Type
Text
Name
movedFrom
2Declare Variable
Type
Text
Name
movedTo
3Declare Variable
Type
Text
Name
landingKind
4RepeatdataCount('Move History') - movesKepttimes
Each time
5Control Data Row
Action Name
addedRow
Operation
Remove
Table
Move History
Row
dataCount('Move History') - 1
6Go Back To The StartFunction
gameRules
gameRules
7RepeatmovesKepttimes
Each time
8Change Variable
Variable
movedFrom
Value
data('Move History', local.index, 'from')
9Change Variable
Variable
movedTo
Value
data('Move History', local.index, 'to')
10Change Variable
Variable
landingKind
Value
data('Move History', local.index, 'landingKind')
11Record PositionFunction
gameRules
gameRules
12Make MoveFunction
gameRules
gameRules
from
movedFrom
to
movedTo
13Set Data Cell
Table
Position
Row
movedTo
Column
"kind"
Value
landingKind
14Pass The TurnFunction
gameRules
gameRules

Take Back Moves keeps the first movesKept Moves, and forgets the rest. The first Repeat removes rows from the bottom of the Move History, one each time round, with Control Data Row’s Operation on Remove.

Next the game goes back to the start. The second Repeat makes each Move it kept, in order. For each one, it records the position first, as Look For Game End does at the start of a Turn. Make Move makes it, the Piece gets the Kind it landed as, and the Turn passes.

Castling, en passant, a Promotion and the fifty-move count all come back as they were. No rule of Undo’s own does that. Make Move does it, the same Make Move as in play.

7.9.3 Undo

Make Undo Data before the Logic, and add it beside Board State with undoData as its slot name. It keeps movesKept while Undo rebuilds the game.

Data StructureUndo Data

What Undo remembers on the Game Rules. movesKept: how many Moves of the Move History stay when the Player's last Turn is taken back (Take Back Moves plays them again).

movesKeptNumberdefault 0
Logic ComponentUndoAttach to: Game Rules

Takes back the Player's last Turn when the Player presses Undo ("undoPressed"): the Computer's reply and the Player's Move before it, or only the Player's Move when the Computer has not replied (it is still thinking, or the game ended on that Move). Then that Turn starts again, as play went: a finished game is played again, and if the Turn is the Computer's (a Player who plays Black, back at the start), the Computer moves again. A Stockfish answer still on its way counts for nothing, because the Game State is no longer Computer's Turn. Undo answers only when a Move has been made, and not while the Promotion choice or a menu (the New Game panel) is open.

Attach toAny Object
DATA STRUCTURES
Board Stateself.boardState
Undo Dataself.undoData
On Undo Pressed
WhenundoPressedCustom Event
1IfdataCount('Move History') > 0
Then
2Change Component Value
Component Value
self.undoData.movesKept
Value
dataCount('Move History') - 1
3Ifself.boardState.sideToMove == self.boardState.playerSide && self.undoData.movesKept > 0
Then
4Change Component Value
Component Value
self.undoData.movesKept
Operator
-=
Value
1
5Take Back MovesFunction
gameRules
self
movesKept
self.undoData.movesKept
6Set Game State
Game State
Playing
7Start The TurnFunction
gameRules
self
8Trigger Custom Event
Custom Event
positionChanged

Undo hears undoPressed. Is there a Move to take back? If so, movesKept starts as every Move but the last. And if it’s your Turn now, the last Move was the Computer’s reply, so your Move before it goes too. Step 4’s Operator is -=.

That If has a second test, self.undoData.movesKept > 0, joined with &&. Play Black, and the Computer’s first Move may be the only one there is. Then there’s no Move of yours to take back with it, and the count must not go below zero.

Take Back Moves does the work. Set Game State turns the sign back to Playing, even on a finished game, and Start The Turn starts this Turn again. If that Turn is the Computer’s, it asks Stockfish once more.

Its description says Undo doesn’t answer while the Promotion choice or the New Game panel is open. No step on the card does that. The Backdrop does. It lies over the buttons while a panel is open, so a press never reaches Undo.

Attach Undo to the Game Rules now. That’s the line on the Game Rules’ card that waited.

7.9.4 Can Undo

FunctionCan Undo

Asks whether the Undo button can be used: once a Move has been made (the Move History has a row). isOn (returned): true when it can.

RETURN TYPEBoolean
ACTIONS
1Declare Variable
Type
Boolean
Name
isOn
Value
false
2IfdataCount('Move History') > 0
Then
3Change Variable
Variable
isOn
Value
true
4Return
Value
isOn

Can Undo asks whether there’s a Move left to take back. Its Return Type is Boolean. The Return hands back isOn, which its caller reads as value.

7.9.5 Show Button On Or Off

FunctionShow Button On Or Off

Turns a button on or off: while it can be used (isOn) it answers presses and is drawn as usual; otherwise it takes no presses and is drawn faded. Each button that is sometimes off calls it after every change on the Board, with the answer of its own Can ... Function (the Undo button: Can Undo). button: the button. isOn: whether it can be used now. offAlpha: how see-through the button is drawn while it is off, from 0 (invisible) to 1 (solid).

PARAMETERS
NameTypeStarts at
buttonObjectStructural
Required Components
Slot Nameui
Component TypeUI Interaction
isOnBooleanNo
offAlphaNumber0.3
ACTIONS
1IfisOn == true
Then
2Change Component Value
Component Value
button.ui.enabled
Value
true
3Set Alpha
Applies to
button
Alpha
1
4Otherwise
5Change Component Value
Component Value
button.ui.enabled
Value
false
6Set Alpha
Applies to
button
Alpha
offAlpha

Show Button On Or Off fades the button when its answer is no. It takes button and isOn. A yes turns the button’s UI Interaction on, at full color. A no turns it off, and draws it at offAlpha, 0.3, faded but still there.

Its button Parameter is an Object, Structural, with a UI Interaction in a slot named ui. That’s how button.ui.enabled reaches the switch. It’s the Object Parameter’s pencil window again, as in Make Move.

7.9.6 Report Undo

Now the button’s job. Report Undo sends undoPressed when the button is pressed. On positionChanged it asks Can Undo, named canUse. Show Button On Or Off takes that answer as canUse.value, with self in button. Here self is the Undo button.

Logic ComponentReport Undo

What the Undo button does: it tells whoever listens (the Game Rules) with "undoPressed". After every change on the Board ("positionChanged"), which the Game Rules also send when the game begins, it asks Can Undo whether the button can be used now, and turns it on or off (Show Button On Or Off).

Attach toAny Object
COMPONENTS
self.uiUI Interaction
On Hud Activated
WhenUI Activated
1Trigger Custom Event
Custom Event
undoPressed
On Position Changed
WhenpositionChangedCustom Event
1Can UndoFunction
Action Name
canUse
2Show Button On Or OffFunction
button
self
isOn
canUse.value

7.9.7 Undo Button

Make Undo Button from Tool Button, as you made Flip Button. Its one addition is Report Undo. The base keeps its shape and tan.

Object variantUndo ButtonVariant of: Tool Button
Logic
Report Undo

Place Undo Button from the Set up card, with Undo for its Text. Nothing new goes on Tool Button itself.

Run the game. Undo sits faded beside New Game. Play e2 to e4, and wait for the reply. Undo wakes up. Press it. Both Moves go, yours and the Computer’s, and the Board is as it began. Undo fades again.

7.10 New Game, One More Check

Logic ComponentNew GameAttach to: Game RulesAddDelete

Starts every game with the Side and the Strength the Player chose last, and lets the Player start a new game. When the game begins (Game Start, before the first Turn), it takes the choices saved on this device (Persistent Values), when the game has them (the Sides and Strengths tables; otherwise, and the first time, Board State's own playerSide and strength), and turns the Board over for a Player who plays Black. When the Player presses New Game ("newGamePressed"), it opens the New Game panel, a menu that holds the game while it is open, showing the current choices as chosen and asking "Replace the current game?" when a game is in progress and has Moves. Each Side or Strength pressed ("sideChosen", "strengthChosen"; the button is its Other) becomes the chosen one. Play ("playPressed") saves the choices and restarts the game, which starts again from the beginning with them.

Attach toAny Object
DATA STRUCTURES
Board Stateself.boardState
When the Game Starts
WhenGame Start
1Load Persistent Value
Action Name
savedSide
Key
"playerSide"
Default
self.boardState.playerSide
2Load Persistent Value
Action Name
savedStrength
Key
"strength"
Default
self.boardState.strength
3Change Component Value
Component Value
self.boardState.playerSide
Value
savedSide.value
4Change Component Value
Component Value
self.boardState.strength
Value
savedStrength.value
3Check Data Row Exists
Action Name
isKnownSide
Table
Sides
Row
savedSide.value
4IfisKnownSide.value == true
Then
5Change Component Value
Component Value
self.boardState.playerSide
Value
savedSide.value
6Check Data Row Exists
Action Name
isKnownStrength
Table
Strengths
Row
savedStrength.value
7IfisKnownStrength.value == true
Then
8Change Component Value
Component Value
self.boardState.strength
Value
savedStrength.value
9Ifself.boardState.playerSide == "Black"
Then
10Change Component Value
Component Value
self.boardState.isFlipped
Value
true
On New Game Pressed
WhennewGamePressedCustom Event
1Change Component Value
Component Value
self.boardState.chosenSide
Value
self.boardState.playerSide
2Change Component Value
Component Value
self.boardState.chosenStrength
Value
self.boardState.strength
3Control Menu
Menu Element
New Game Panel
4Set Menu Pause State
Menu Element
New Game Panel
5Check Game State
Action Name
isOver
Game State
Game Over
6Ifself.boardState.lastFrom != "" && isOver.value == false
Then
7Set UI Element Visibility
Element
Replace Question
8Otherwise
9Set UI Element Visibility
Element
Replace Question
Visible
No
10Trigger Custom Event
Custom Event
newGameChoiceChanged
On Side Chosen
WhensideChosenCustom Event
1Change Component Value
Component Value
self.boardState.chosenSide
Value
other.newGameOption.option
2Trigger Custom Event
Custom Event
newGameChoiceChanged
On Strength Chosen
WhenstrengthChosenCustom Event
1Change Component Value
Component Value
self.boardState.chosenStrength
Value
other.newGameOption.option
2Trigger Custom Event
Custom Event
newGameChoiceChanged
On Play Pressed
WhenplayPressedCustom Event
1Save Persistent Value
Action Name
persistentWriteResult
Key
"playerSide"
Value
self.boardState.chosenSide
2Save Persistent Value
Action Name
persistentWriteResult2
Key
"strength"
Value
self.boardState.chosenStrength
3Restart Game

New Game used to trust whatever Side and Strength it found saved. Now it checks first. Check Data Row Exists asks the Sides table, and then the Strengths table, whether it has a row of that name. A saved word the game doesn’t know is passed over, and Board State keeps its own White and Casual. Why now? From this chapter, Ask The Computer reads the Strength’s row of Strengths. A word with no row there would leave the Computer nothing to read. Each If reads that check’s answer. The new steps go in the middle of the line, between steps 2 and 9.

Here’s a quiet surprise. Play as Black, and the Computer moves first. There’s no step for it. White’s first Turn starts, Look For Game End sends gameContinues, and it’s the Computer’s Turn.

Play it!

Watch for each of these.

  • Start a game as White, and Undo is faded. Play e2 to e4. Thinking… shows, and a Black Piece glides to its Square, and Your move comes back.
  • Click a Black Piece while the words say Thinking…. Nothing answers.
  • After a reply, press Undo. Your Move and the reply both go, and Undo fades.
  • Press New Game, choose Black, and press Play. The Board turns. The Computer makes White’s first Move, and a White Piece glides on the far side of the Board.
  • Choose Gentle, and play a few Moves. Try Expert after that. Expert thinks for 1.2 seconds against Gentle’s 0.2, and it plays a good deal better.
  • If the Computer castles, its King and its Rook glide together.
  • Press Flip while a Piece is gliding. The glide is over in a moment, so give yourself time: set slideSeconds to 3 on Slide Piece’s Shared Variables card, for one run. The Piece lands at once, in its place on the turned Board. Then put slideSeconds back to 0.36.
How it works

The game asks, and goes on. Stockfish answers with a message, and the game checks the Move before it trusts it. The Moving Piece glides it home. Make Move makes it, the same Make Move as yours, and the Move History writes it down. Undo makes every Move again from the start.

Underneath is one idea. The Move History is the whole game, and the Board follows from it. So taking a Move back needs no rule of its own. The game starts over without the last Move.

7.11 If It Didn’t Work

This is a long chapter, with messages that cross between the Game Rules, the Library and the Moving Pieces. A slip somewhere is normal. Watch what the game does, and think it through.

A block drawn in red, with a number on the Errors bar? Open the bar. It names the block and what it misses. New Game may still show Chapter 6’s two false Number errors for its saved words. Keep those Values as the card shows. For another error, compare its block with the card, including each quote mark and prefix.

It says Thinking… and stays there, and nothing moves? Stockfish may never have heard the question, so look at Ask The Computer’s Run Code line, letter by letter, and the Library’s Alias, stockfishBridge. Or the answer came, and nobody listened. Is Make Computer Move attached to the Game Rules?

Opponent disconnected shows under the Board, twenty seconds or more after your Move? That’s the clock from Ask The Computer, ringing. Perhaps the Library’s file didn’t import whole, so import stockfish-bridge.js again from the zip.

The Computer’s Piece jumps, and doesn’t glide? Perhaps your computer asks for less motion, and that’s the game being kind to it. If not, look at the two Tween steps.

The Piece glides, but the Move never happens? Only the first Moving Piece says when it lands, so its saysWhenLanded must be Yes, and the Rook’s Off.

You see two of the same Piece during a slide? Look at Show Piece’s new Event, and its != -1.

Undo stays faded? Report Undo’s On Position Changed may have no arrow into Can Undo or Show Button On Or Off. Its isOn must read canUse.value. Undo wakes, but a press does nothing? Then look at the Game Rules, and whether Undo is attached to them. Undo answers, but takes back too much or too little? Look at its step 3 If, and its two tests, joined with &&: your Turn now, and a Move left to keep.

Each of these is one small fix. Make it, run the game again, and you’re back with the chapter. The catch-up download in the Goal is this chapter’s game, finished, if you’d like to compare.

Challenge

The Computer plays at five Strengths, each one a row of Strengths. What would a sixth be? A Beginner below Gentle, maybe, with a skillLevel of 0 and almost no thinking time. Or a Patient one that thinks for three seconds. Add the row, and a button for it on the panel, a Strength Option placed once more. How your Computer plays is up to you.

Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).

Your game has an opponent now, one that thinks. In Chapter 8, when you’re stuck, you’ll ask it for a little advice.