Build a GameCreating Chess

3  Turns and Check

Goal

By the end of this chapter, White moves first and the Sides take turns. No Move may leave its own King attacked. A King in Check turns red, and the words under the Board say so.

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 4 from it.

Chess, Chapter 3 finishedMyth project · 15.5 MB

To open it, start Myth Engine, choose File › Open Project... and pick the downloaded file.

3.1 The Idea

Play your Board from Chapter 2 for a moment. Move a White Pawn, then another White Pawn, then a Black Knight. Nothing stops you. A King can walk straight into a Rook’s line, and the game lets it.

By the end of this chapter, the game keeps the rules. White moves first, and after that the Sides take turns, Black, then White, then Black again. Under the Board, in gray-green, two words wait: Your move. When a King is attacked, its Square turns red, and the words say Check.

Keeping each Turn is the small part. The Game Rules remember one word, White or Black, and change it after every Move.

The real question is a harder one. How does the game know a King is attacked?

You could ask every enemy Piece where it may go, the way Find Moves does, and look for the King among the dots. That’s a great deal of walking, every Turn. There’s a shorter way, and it starts from the King’s side.

Stand on the King’s Square, and look out along a line, the way a Rook would come. Look up the File, one Square at a time. The first Piece you meet is the only one on that line that could reach you. Everything behind it is blocked. So if that first Piece is an enemy Rook, the King is attacked. If it’s anything else, that line is safe.

It’s like holding a lamp on the King’s Square and shining it down each line. Whatever the light falls on first is the one that matters. Do that for every Direction of every Kind, and you know whether anything could reach the King from anywhere on the Board.

That’s a Check: the King of the Side to move is attacked. And a Legal Move is one that leaves your own King safe. To find out, the game makes the Move in Position, asks whether the King is attacked, and puts everything back. Try, check, take back. If the King would be attacked, the dot never shows.

Chapter 2 also left a promise. Its game opened with a faint dot on every Square, until the first click. This chapter’s game opens clean.

3.2 The Plan

Here’s how the pieces work together. As before, read each line from left to right. A name in bold is a piece you’ll make or change. Read the lines once for the shape, and come back after Only Legal Moves.

  • The game begins -> Start Turn asks Look For Check.
  • Look For Check -> Find King finds the King of the Side to move -> Is Square Attacked looks out from its Square.
  • Is Square Attacked -> Find Attacker Along looks down one line at a time.
  • Look For Check -> the Status Line shows Your move or Check.
  • Start Turn sends positionChanged.
  • You click a Piece of the Side to move -> Select and Move asks Find Moves, and after it Keep Safe Moves.
  • Keep Safe Moves -> Drop Move If Unsafe tries each Move with Move Piece, and takes it back.
  • You click a mark -> Select and Move makes the Move with Move Piece, and tells the Game Rules moveMade.
  • Start Turn hears it -> the Turn passes.
  • Select and Move sends positionChanged -> Square Marks turns a King in Check red.

You’ll build it in the order the pieces need each other. First comes what the Game Rules remember. After that come the two Functions that answer whether a Square is attacked, and the Turn. Last are the Legal Moves and the red Square. You’ll run the game twice on the way, with part of it working.

3.3 Set Up

Set upWhat this chapter adds
GLOBAL VARIABLES
$statusTextstarts at
SCENE Chess Table: PLACE THESE
ObjectXY
Status Line070

This chapter’s Set up card brings two new kinds of line. GLOBAL VARIABLES makes $status, a value the whole game shares, which will hold the words under the Board and starts out empty. PLACE THESE puts the Status Line on the screen, 70 pixels above the bottom edge. The Set up card has a paragraph on each.

Make the Global now. Place the Status Line once you’ve made it, in the first part.

3.4 What the Game Rules Remember Now

The Game Rules need two more things in their Board State: whose Turn it is, and which Square holds a King in Check.

Data StructureBoard StateAddDelete

What the Game Rules remember about the game besides the Position table. sideToMove: the Side whose Turn it is (White moves first). selected: the Square of the selected Piece (empty when none is selected). lastFrom and lastTo: the two Squares of the last Move (empty before the first Move). checkSquare: the Square of the King in Check (empty when the Side to move is not in Check).

sideToMoveTextdefault White
selectedTextdefault (empty)
lastFromTextdefault (empty)
lastToTextdefault (empty)
checkSquareTextdefault (empty)

Open Board State and add the two fields. sideToMove is Text, with White as its default, because White moves first. checkSquare is Text and starts empty, so clear its 0. The card lists sideToMove first. Yours will sit at the bottom, and that’s fine, because the game reads each field by its name.

Next, the Sides learn who their opponent is.

Data StructureSides EntryAddDelete

One row of the "Sides" Data Table, which follows it. One row per Side. forward: the way its Pawns move along the Ranks (1 = up, toward Rank 8; -1 = down). pawnRank: the Rank its Pawns start on. opponent: the other Side.

forwardNumberdefault 1
pawnRankNumberdefault 2
opponentTextdefault (empty)
Data TableSidesData Structure: Sides EntryAddDelete
Row 0White
forward1
pawnRank2
opponentBlack
Row 1Black
forward-1
pawnRank7
opponentWhite

Open Sides Entry and add a field, opponent, a Text with its Value cleared. Sides shows the new column at once. Double-click each new cell after that: White’s opponent is Black, and Black’s is White. The game swaps Turns by reading this column.

The words under the Board live in a table of their own. That way, they’re all in one place.

Data StructureWords Entry

One row of the "Words" Data Table, which follows it. The words the Player reads, one row per message, so they are found and changed in one place. text: the words as shown.

textTextdefault (empty)
Data TableWordsData Structure: Words Entry
Row 0Your Move
textYour move
Row 1Check
textCheck

Words has one Text column, text, and two rows. Make it as you made Kinds: its Words Entry gets the one field, a Text with its Value cleared, as before. The row names are what the Logic asks for. Each row’s text is what the player reads. Type the text with only its first letter a capital, so Your Move’s text is Your move.

Now the Object that shows them.

ObjectStatus Line
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorBottom Center
Presentation > Render LayerUI
Bounding Box > SizeX 32, Y 32
UI Interaction
Element TypeText
Text / UI
Text{$status}
Font Size28
EmphasisSemibold
Color#62745F
AlignmentCenter

The Status Line is your first Screen UI Object. It lives on the screen, not on the Board, so it never moves when anything else does. In the Create Object window, pick Screen UI Object as its type. Its Space and Render Layer come set already, and so does its Bounding Box. Its Screen Anchor is a small grid of nine points. Pick the one at the bottom middle, Bottom Center. Its UI Interaction comes attached, too. Make sure its Element Type says Text, because the player reads the Status Line and never presses it.

Attach a Text / UI, as you did for the Rank Label. Its Text is {$status}, braces and all. That’s the Global, shown live: whatever $status holds, the Status Line shows the moment it changes. Its Font Size is 28, counted in pixels here, because it lives on the screen. Semibold, the gray-green color and Center come last.

Now place it, as the Set up card says, with its X and Y in Screen Offset (px).

Run the game. It looks the same as Chapter 2’s. $status is empty, so the Status Line has nothing to show yet.

3.5 Is a Square Attacked?

Now the chapter’s hard idea, the lamp on the King’s Square. Two Functions make it. The first looks down one line.

3.5.1 Find Attacker Along

This one is Follow Direction, walking the other way. Take it slowly.

Find Attacker Along is handed a Square, square, one row of Directions, direction, and the Side that might be attacking, bySide. It walks back from the Square along that row, one step at a time. While each Square it lands on is empty, it keeps going. At the first Piece, it stops. Is that Piece bySide’s, and of the row’s Kind? If so, that Piece could capture onto the Square, and attackers becomes 1. Anything else, and attackers stays 0.

Why back? Take the Rook’s row named Rook down. A Rook that comes down the File to reach e1 starts somewhere above e1. So to find it, the walk from e1 goes up, the opposite way to the row. Each step takes the fileStep and rankStep away instead of adding them.

Take White’s King on e1, and a Black Rook on e8, nothing between. The walk for the Rook’s down row starts at e1 and goes up: e2, e3, and on up the File. Every Square is empty, so it keeps going. On e8 it meets a Piece. It’s Black, it’s a Rook, and the row is a Rook’s row, so the answer is 1.

Put a White Pawn on e4, and the same walk stops there. A Pawn isn’t a Rook, so that line is safe, and the answer stays 0.

Pawns need one more thought. A Pawn captures diagonally forward, and forward depends on its Side. So the walk multiplies each rankStep by bySide’s forward, 1 or -1, as Follow Direction did. Then a Black Pawn’s capture is found above the Square. A White Pawn’s is below.

The card multiplies every row that way, the Rook’s and the Bishop’s too. Each of their rows may flip. The set of lines stays the same. Their rows come in pairs, one up and one down, so a flipped row is its partner, and every line still gets its look.

FunctionFind Attacker Along

Looks back from one Square along one direction of the Directions table, Square by Square, for the first Piece in the way. attackers (returned): 1 when that Piece belongs to bySide and is of the direction's Kind, so it could capture onto the Square, else 0 (for a Pawn, the direction is turned round by its Side's forward). square: the Square looked from (a1 to h8). direction: the row (0 = first) of the Directions table. bySide: the attacking Side.

PARAMETERS
NameTypeStarts at
squareText
directionNumber0
bySideText
RETURN TYPENumber
ACTIONS
1Declare Variable
Name
forward
Value
1
2Declare Variable
Name
file
Value
0
3Declare Variable
Name
rank
Value
0
4Declare Variable
Name
stepsLeft
Value
0
5Declare Variable
Type
Boolean
Name
isOnBoard
Value
false
6Declare Variable
Name
index
Value
0
7Declare Variable
Type
Boolean
Name
keepLooking
Value
true
8Declare Variable
Name
attackers
Value
0
9Change Variable
Variable
forward
Value
data('Sides', bySide, 'forward')
10Change Variable
Variable
file
Value
data('Position', square, 'file')
11Change Variable
Variable
rank
Value
data('Position', square, 'rank')
12Change Variable
Variable
stepsLeft
Value
data('Directions', direction, 'steps')
13WhilekeepLooking == true && stepsLeft > 0
Each time
14Change Variable
Variable
file
Operator
-=
Value
data('Directions', direction, 'fileStep')
15Change Variable
Variable
rank
Operator
-=
Value
data('Directions', direction, 'rankStep') * forward
16Change Variable
Variable
stepsLeft
Operator
-=
Value
1
17Change Variable
Variable
isOnBoard
Value
false
18Iffile >= 1 && file <= 8 && rank >= 1 && rank <= 8
Then
19Change Variable
Variable
isOnBoard
Value
true
20Change Variable
Variable
index
Value
(rank - 1) * 8 + (file - 1)
21Change Variable
Variable
keepLooking
Value
false
22IfisOnBoard == true && data('Position', index, 'kind') == ""
Then
23Change Variable
Variable
keepLooking
Value
true
24IfisOnBoard == true && data('Position', index, 'side') == bySide && data('Position', index, 'kind') == data('Directions', direction, 'kind')
Then
25Change Variable
Variable
attackers
Value
1
26Return
Value
attackers

Look on the card for keepLooking, which works as keepGoing did. And look for the -= lines of steps 14 and 15: that’s the walk going back. Its eight Declares mostly start at 0 or false. The forward one starts at 1, and keepLooking is a Boolean starting at true, so the While runs the first time. Its RETURN TYPE is Number, and its Return hands back attackers.

Step 20 turns the file and rank back into a row number, index, the way Look At Square did in Chapter 2. Steps 22 and 24 read Position by that number.

Step 18’s If joins four tests with &&, and step 24’s joins three. Type each condition whole, as the card spells it.

3.5.2 Is Square Attacked

Now the lamp turns all the way round.

Go back to the lamp on e1, the King’s Square, with the Rook’s line in its light. Find Attacker Along shines it down one line. Is Square Attacked turns it to every line there is. That’s up the File and down it, along the Rank both ways, the four diagonals, and the eight jumps a Knight could make. A Queen and a King have rows of their own in Directions, so they’re found the same way. Every line that lights up an enemy adds one to a tally, attackerCount. At the end, one look at the tally answers the question. Anything over 0 means attacked.

The lines are the rows of Directions, the same rows Find Moves walks forward. So the card is a Repeat over that table.

A Pawn’s forward row can’t capture, so its If leaves that row out. A Pawn standing in front of a King never attacks it.

It hands back two answers at once, so they travel together in Is Square Attacked Result, as Square Position’s x and y did. Make that Data Structure first, from its card, and pick it as the Function’s Return Type.

Data StructureIs Square Attacked Result

What Is Square Attacked returns. attacked: yes when at least one Piece of the attacking Side could capture onto the Square. attackers: how many could.

attackedBooleandefault false
attackersNumberdefault 0
FunctionIs Square Attacked

Answers whether any Piece of one Side could capture onto a Square. square: the Square (a1 to h8). bySide: the attacking Side (White or Black). attacked (returned): yes when at least one of its Pieces attacks the Square. attackers (returned): how many do.

PARAMETERS
squareText
bySideText
RETURN TYPEIs Square Attacked Result (a Data Structure)
ACTIONS
1Declare Variable
Name
attackerCount
Value
0
2Declare Variable
Type
Boolean
Name
attacked
Value
false
3RepeatdataCount('Directions')times
Each time
4Ifdata('Directions', local.index, 'canCapture') == true
Then
5Find Attacker AlongFunction
Action Name
attackerLook
square
square
direction
local.index
bySide
bySide
6Change Variable
Variable
attackerCount
Operator
+=
Value
attackerLook.value
7IfattackerCount > 0
Then
8Change Variable
Variable
attacked
Value
true
9Return
attacked
attacked
attackers
attackerCount

Its Return has a row for each field: attacked gets attacked, and attackers gets attackerCount.

Step 5’s Function block is the call, named attackerLook. Step 6 adds its answer on with +=. A Function that hands back one number calls it value, so the answer is attackerLook.value, and the count grows by one for each line that finds an attacker.

Two Functions, and still nothing to see. The next part puts a question to them, the one the whole chapter has been waiting to ask.

3.6 Whose Turn It Is

Now the game learns to start a Turn.

3.6.1 Find King

Before the game can ask whether a King is attacked, it has to find the King.

Find King is handed a Side. It goes down Position, all 64 rows. On the row whose kind is King and whose side is that Side, it keeps the row’s name in kingSquare. That’s the King’s Square, e1 at the start for White.

FunctionFind King

Finds where one Side's King stands. side: White or Black. kingSquare (returned): its Square (a1 to h8).

PARAMETERS
sideText
RETURN TYPEText
ACTIONS
1Declare Variable
Type
Text
Name
kingSquare
2RepeatdataCount('Position')times
Each time
3Ifdata('Position', local.index, 'kind') == "King" && data('Position', local.index, 'side') == side
Then
4Change Variable
Variable
kingSquare
Value
dataRow('Position', local.index)
5Return
Value
kingSquare

Its If joins two tests with &&. The first compares the kind with "King", in quote marks, because it’s a word. The second compares the side with side, the Function’s own Parameter, so it goes in bare. Its RETURN TYPE is Text, and the Return hands back kingSquare.

3.6.2 Look For Check

Now the question itself. Is the Side to move in Check?

Look For Check is handed the Game Rules, as gameRules. It reads whose Turn it is from their Board State, and the other Side from Sides. It finds that Side’s King with Find King. Then it asks Is Square Attacked about the King’s Square, with the other Side as the attacker.

If the answer is yes, the Board State remembers the King’s Square as checkSquare, and $status takes the word Check. If not, checkSquare is emptied, and $status takes Your move.

FunctionLook For Check

Asks whether the Side to move is in Check: whether its King's Square is attacked by the other Side. The Board State remembers the answer (checkSquare: the King's Square, or empty), and the status line's words ($status) say "Check" or "Your move". gameRules: the Game Rules Object, whose Board State says whose Turn it is.

PARAMETERS
NameTypeStarts at
gameRulesObjectStructural
Required Components
Slot NameboardState
Component TypeData Structure
Required SchemaBoard State
ACTIONS
1Declare Variable
Type
Text
Name
side
2Declare Variable
Type
Text
Name
enemy
3Declare Variable
Type
Text
Name
kingSquare
4Change Variable
Variable
side
Value
gameRules.boardState.sideToMove
5Change Variable
Variable
enemy
Value
data('Sides', side, 'opponent')
6Find KingFunction
Action Name
kingLook
side
side
7Change Variable
Variable
kingSquare
Value
kingLook.value
8Is Square AttackedFunction
Action Name
checkLook
square
kingSquare
bySide
enemy
9IfcheckLook.attacked == true
Then
10Change Component Value
Component Value
gameRules.boardState.checkSquare
Value
kingSquare
11Change Variable
Variable
$status
Value
data('Words', 'Check', 'text')
12Otherwise
13Change Component Value
Component Value
gameRules.boardState.checkSquare
Value
''
14Change Variable
Variable
$status
Value
data('Words', 'Your Move', 'text')

Its one Parameter is gameRules, an Object, made on the Start block as Show Piece On Square’s piece was. Its pencil window takes Structural, and a Required Component, a Data Structure that is a Board State, in a slot named boardState.

Step 7 reads Find King’s answer as kingLook.value, and step 9 asks whether checkLook.attacked is true. Steps 10 and 13 are Change Component Values on another Object, the Game Rules. Their paths start gameRules, not self. Steps 11 and 14 change the Global. Type $status into each one’s Variable box, with the $. The $ is left off only once, when you name the Global in GLOBAL VARIABLES. The Value reads one cell of Words. Its row name, 'Check' or 'Your Move', goes in quote marks, capital M and all.

3.6.3 Start Turn

Now the piece that runs it all, once at the start and once after every Move.

Start Turn sits on the Game Rules, beside Select and Move. When the game begins, it asks Look For Check about White. That puts Your move under the Board. Then it sends positionChanged, so every Square and mark shows the Board as it is. That’s the promise from Chapter 2, kept. The dots go before you ever see them.

After a Move, Select and Move will send it moveMade. Start Turn then reads whose Turn it was, and gives the Turn to that Side’s opponent in Sides. Then it asks Look For Check again, about the new Side.

Logic ComponentStart TurnAttach to: Game Rules

Starts each Turn: the first one (White's) when the game begins, and the next one after every Move (Select and Move sends "moveMade"). It gives the Turn to the other Side and asks whether that Side is in Check (Look For Check), which sets the Check mark and the status line.

Attach toAny Object
DATA STRUCTURES
Board Stateself.boardState
When Created
WhenCreate
1Look For CheckFunction
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')
4Look For CheckFunction
gameRules
self

Its DATA STRUCTURES row is Board State. It has two Events: Create, and a Custom Event, moveMade, which nothing sends yet. So make it with Add Custom Event….

In each call to Look For Check, gameRules is a list, and it starts on self. Leave it there. Here self is the Game Rules, the Object Start Turn is attached to.

ObjectGame RulesAddDelete
Data Structure
Data StructureBoard State
Logic
Select and Move
Start Turn

Attach Start Turn to the Game Rules.

Run the game. The Board comes up clean, with no dots, and under it, in gray-green: Your move. Move a White Pawn, then another. The words never change, and either Side still moves. Nothing sends moveMade yet. That comes in the next part.

3.8 The Red Square

Now the Board points at the King.

3.8.1 Square Marks

Square Marks already shows the gold of a selected Piece and the yellow of the last Move. Now it shows a third mark, the red of a King in Check. Three marks can land on one Square, so the order decides which one you see.

Each time positionChanged arrives, the Square first hides its tint. After that, it asks three questions, one after the other, from the least important to the most. Was it part of the last Move? It takes the soft yellow of Chapter 2, the color of the last Move. Is its Piece selected? The gold goes on over the yellow, if there was any. Is its King in Check? Red, over both. The last answer that says yes is the one that shows.

Most of Square Marks is built again, so here is its whole card as it ends this chapter, not a Changes card. Three things are new: the When Created Event is gone, two Shared Variables are added, and the positionChanged line is new from top to bottom.

Logic ComponentSquare MarksAttach to: Square

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.

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

The When Created Event goes first. Start Turn’s positionChanged reaches every Square when the game begins, so nothing needs to hide them sooner. Right-click the Event’s block and choose Remove Event and Its Blocks.

Then the Shared Variables. The card’s last two, checkColor and checkAlpha, are the new ones, so add them with the + on the Shared Variables card. The red shows at 0.66, the strongest of the three.

Now the line under positionChanged. The old one was an If with the gold, an Else If with the yellow, and an Else that hid the Square. Right-click the If and choose Delete. Its panels go with it, and if the Else If or the Else stays behind, delete it the same way. The line is empty now. Add the ten steps down the card. Steps 2, 5 and 8 are three Ifs, one after another, each at the same indent. Steps 5 to 7 are the gold again, word for word as the old If and its Then had them, now in their new place.

Run the game. Play e2 to e4, f7 to f6, then the Queen from d1 to h5. Black’s King on e8 sits on a red Square, and the words say Check. Play g7 to g6. The red is gone, and the words say Your move.

Your Board keeps the rules now.

Play it!

Watch for each of these.

  • At the start, no dots anywhere, and Your move under the Board.
  • Click a Black Piece first. Nothing lights, because White moves first.
  • Play e2 to e4, then click any White Piece, and nothing lights, because now it’s Black’s Turn.
  • Play f7 to f6, then White’s Queen from d1 to h5. Black’s King on e8 turns red, and the words say Check.
  • Click Black’s a7 Pawn. Its Square turns gold, with no dots.
  • Click g7. One dot, on g6. Play it, and the red goes.
  • In a new game, play d2 to d4, e7 to e5, the Knight from b1 to c3, and Black’s Bishop from f8 to b4. Click the Knight on c3. No dots: it stands between its King and the Bishop.
How it works

The Game Rules remember whose Turn it is, and a Move sends moveMade, so the Turn passes. Each Turn begins by asking one question: is this King attacked? To answer it, the game stands on the King’s Square and looks out along every line a Piece could come by. A Move that would leave the King attacked is tried, found out, and taken back, before its dot ever shows.

Underneath it all is the same idea as before. The table is the truth. To ask what would happen, the game changes the table, looks, and puts it back.

3.9 If It Didn’t Work

Something in a chapter this size may be a little off. That’s expected. Play a few Moves, 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. Hold that block up to the card, quote marks, @ and $ included.

Nothing under the Board at all? Perhaps the Status Line’s Text isn’t {$status}, braces and all. Perhaps Start Turn isn’t attached to the Game Rules. Or its When Created Event’s call to Look For Check has no self picked in gameRules.

Dots all over the Board at the start? Start Turn’s When Created isn’t sending positionChanged, so look for its step 2, and check that it’s joined.

Your move, but either Side still moves? Select and Move’s step 13 still asks whether the Square has a kind. Its condition should start by comparing the clicked Square’s side with self.boardState.sideToMove.

Only White ever moves? Then the Turn never passes. Perhaps moveMade isn’t sent, or Start Turn’s second Event says something a letter off. Both must read moveMade, capital M. Or Sides’ opponent column is still empty, with no Side to pass the Turn to.

A Piece turns gold, but no dots ever show? Keep Safe Moves is dropping every Move, as if your own Pieces were the attackers. Look at its step 5. The enemy comes from Sides: data('Sides', side, 'opponent').

Click a Piece, and it vanishes from its Square while its dots appear? Its Move was tried and never taken back, and the last two steps then emptied the Square it was tried on. Look for Drop Move If Unsafe’s step 13, the Move Piece with to in from and from in to.

Check under the Board when no King is attacked? Find Attacker Along’s walk may be going forward instead of back. Steps 14 and 15 use -=.

The red shows, but under the gold or the yellow? Square Marks’ three Ifs are in the wrong order, and they should run last Move, then selected, then Check.

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

Every word under the Board comes from the Words table. Change Your move to anything you like, in any language you like, and the game says it. And think about what else a Turn could do. What would your game do if the Side to move had no Legal Move at all? Chapter 5 has one answer, and there may be others.

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

White moves, then Black, and no Move may leave its own King open to attack. In Chapter 4, the three Moves that surprise new players arrive.