- Learn
- Build a Game
- Chess
- 3 Turns and Check
3 Turns and Check
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.
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
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.
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).
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.
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.
12Black-17WhiteOpen 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.
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.
Your moveCheckWords 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.
Window / UIBottom CenterUIX 32, Y 32Text{$status}28Semibold#62745FCenterThe 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.
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.
- Name
forward- Value
1
- Name
file- Value
0
- Name
rank- Value
0
- Name
stepsLeft- Value
0
- Type
Boolean- Name
isOnBoard- Value
false
- Name
index- Value
0
- Type
Boolean- Name
keepLooking- Value
true
- Name
attackers- Value
0
- Variable
forward- Value
data('Sides', bySide, 'forward')
- Variable
file- Value
data('Position', square, 'file')
- Variable
rank- Value
data('Position', square, 'rank')
- Variable
stepsLeft- Value
data('Directions', direction, 'steps')
keepLooking == true && stepsLeft > 0- Variable
file- Operator
-=- Value
data('Directions', direction, 'fileStep')
- Variable
rank- Operator
-=- Value
data('Directions', direction, 'rankStep') * forward
- Variable
stepsLeft- Operator
-=- Value
1
- Variable
isOnBoard- Value
false
file >= 1 && file <= 8 && rank >= 1 && rank <= 8- Variable
isOnBoard- Value
true
- Variable
index- Value
(rank - 1) * 8 + (file - 1)
- Variable
keepLooking- Value
false
isOnBoard == true && data('Position', index, 'kind') == ""- Variable
keepLooking- Value
true
isOnBoard == true && data('Position', index, 'side') == bySide && data('Position', index, 'kind') == data('Directions', direction, 'kind')- Variable
attackers- Value
1
- 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.
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.
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.
- Name
attackerCount- Value
0
- Type
Boolean- Name
attacked- Value
false
dataCount('Directions')timesdata('Directions', local.index, 'canCapture') == true- Action Name
attackerLook- square
square- direction
local.index- bySide
bySide
- Variable
attackerCount- Operator
+=- Value
attackerLook.value
attackerCount > 0- Variable
attacked- Value
true
- 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.
Finds where one Side's King stands. side: White or Black. kingSquare (returned): its Square (a1 to h8).
- Type
Text- Name
kingSquare
dataCount('Position')timesdata('Position', local.index, 'kind') == "King" && data('Position', local.index, 'side') == side- Variable
kingSquare- Value
dataRow('Position', local.index)
- 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.
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.
boardStateData StructureBoard State- Type
Text- Name
side
- Type
Text- Name
enemy
- Type
Text- Name
kingSquare
- Variable
side- Value
gameRules.boardState.sideToMove
- Variable
enemy- Value
data('Sides', side, 'opponent')
- Action Name
kingLook- side
side
- Variable
kingSquare- Value
kingLook.value
- Action Name
checkLook- square
kingSquare- bySide
enemy
checkLook.attacked == true- Component Value
gameRules.boardState.checkSquare- Value
kingSquare
- Variable
$status- Value
data('Words', 'Check', 'text')
- Component Value
gameRules.boardState.checkSquare- Value
''
- 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.
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.
Any Objectself.boardState- gameRules
self
- Custom Event
positionChanged
- Type
Text- Name
side
- Variable
side- Value
self.boardState.sideToMove
- Component Value
self.boardState.sideToMove- Value
data('Sides', side, 'opponent')
- 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.
Board StateAttach 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.7 Only Legal Moves
Now the game stops a Move that would leave its own King attacked. First comes a small piece.
3.7.1 Move Piece
Select and Move already does this with four Set Data Cells. Now a second piece of Logic needs the same four, so they move into a Function of their own.
Think of a hand over the Board. It lifts the Piece on from and sets it down on to. Whatever stood on to is knocked off. That’s all a Capture is to the table.
Moves the Piece on one Square to another in the Position table: the Piece takes the new Square (and any Piece that stood there is gone), and its old Square becomes empty. from and to: the two Squares (a1 to h8).
- Table
Position- Row
to- Column
"kind"- Value
data('Position', from, 'kind')
- Table
Position- Row
to- Column
"side"- Value
data('Position', from, 'side')
- Table
Position- Row
from- Column
"kind"- Value
''
- Table
Position- Row
from- Column
"side"- Value
''
Its Table is a list, and Position is the one to pick from it. Its Columns go in quote marks, "kind" and "side", as in Chapter 2, and its Rows hold to and from, bare: this Function’s own Parameters.
3.7.2 Drop Move If Unsafe
Here’s the try, check, take back.
Drop Move If Unsafe is handed one marked Move, from and to, with where the mover’s King stands and who the enemy is. First it remembers what stands on to, in takenKind and takenSide. Then it makes the Move with Move Piece.
Now, where is the King? If the Piece that moved was the King itself, it’s on to now. Otherwise it’s where it was. Either way, that Square goes into checkSquare. That’s a name this Function declares, the same as the Board State’s field, and it leaves the red Square alone. Is Square Attacked looks out from it with the enemy as the attacker. If the enemy could capture there, the Move is unsafe, and its row in Targets is set to false. Its dot never shows.
Then it takes the Move back. Move Piece runs again, from to back to from. The two last steps put back whatever stood on to, from takenKind and takenSide. Position is exactly as it was. Nobody saw a thing.
Tries one marked Move on the Position table, asks whether the mover's own King is then attacked, and takes the Move back, so the Position is as it was; if the King would be attacked, the Move is unmarked in the Targets table. from and to: the Squares of the Move (a1 to h8). kingSquare: where the mover's King stands now. enemy: the other Side.
- Type
Text- Name
takenKind
- Type
Text- Name
takenSide
- Type
Text- Name
checkSquare
- Variable
takenKind- Value
data('Position', to, 'kind')
- Variable
takenSide- Value
data('Position', to, 'side')
- from
from- to
to
- Variable
checkSquare- Value
kingSquare
from == kingSquare- Variable
checkSquare- Value
to
- Action Name
kingLook- square
checkSquare- bySide
enemy
kingLook.attacked == true- Table
Targets- Row
to- Column
"reachable"- Value
"false"
- from
to- to
from
- Table
Position- Row
to- Column
"kind"- Value
takenKind
- Table
Position- Row
to- Column
"side"- Value
takenSide
Step 12’s Value is "false", the word in quote marks, as "true" was in Look At Square. The column it writes is a Boolean, so the word lands there as false, the same false that Keep Safe Moves compares with true. Its Row is to, bare, and so are the Rows of steps 14 and 15. Steps 6 and 13 call Move Piece. Each one’s from and to are boxes on the block. Step 13 swaps them: to goes back to from, and the Move is undone as if it never happened.
3.7.3 Keep Safe Moves
Find Moves marks every Square a Piece could reach. Keep Safe Moves goes over those marks and keeps only the Legal Moves.
Think of it as an inspector with a clipboard. Before it starts, it notes three things it will need at every mark: whose Piece this is, who the enemy is, and where its own King stands. Then it walks down Targets. At each Square marked reachable, it hands the Move to Drop Move If Unsafe, which tries it and takes it back. A mark that would leave the King attacked comes off. The rest stay.
Of the Squares marked in the Targets table for the Piece on one Square, unmarks every one that would leave its own King attacked, so only Legal Moves stay marked. from: the Piece's Square (a1 to h8).
- Type
Text- Name
side
- Type
Text- Name
enemy
- Type
Text- Name
kingSquare
- Variable
side- Value
data('Position', from, 'side')
- Variable
enemy- Value
data('Sides', side, 'opponent')
- Action Name
kingLook- side
side
- Variable
kingSquare- Value
kingLook.value
dataCount('Targets')timesdata('Targets', local.index, 'reachable') == true- from
from- to
dataRow('Targets', local.index)- kingSquare
kingSquare- enemy
enemy
Step 10’s to is dataRow('Targets', local.index), the name of the row the Repeat is on. Targets has its rows in Position’s order, so that name is a Square.
3.7.4 Select and Move
Now the click learns the rules.
Decides what a click on a Square means. A click on a Square the selected Piece may move to moves it there (taking any Piece on it), remembers the Move, and tells the Game Rules "moveMade" (Start Turn then starts the other Side's Turn); a click on a Piece of the Side to move selects it and finds its Legal Moves; any other click clears the selection. Then it tells everyone "positionChanged". Its Other is the clicked Square.
Any Objectself.boardState- Type
Text- Name
selectedSquare
- Type
Text- Name
clickedSquare
- Variable
clickedSquare- Value
other.squareInfo.name
- Variable
selectedSquare- Value
self.boardState.selected
selectedSquare != "" && data('Targets', clickedSquare, 'reachable') == true- Table
Position- Row
clickedSquare- Column
"kind"- Value
data('Position', selectedSquare, 'kind')
- Table
Position- Row
clickedSquare- Column
"side"- Value
data('Position', selectedSquare, 'side')
- Table
Position- Row
selectedSquare- Column
"kind"- Value
''
- Table
Position- Row
selectedSquare- Column
"side"- Value
''
- from
selectedSquare- to
clickedSquare
- Component Value
self.boardState.lastFrom- Value
selectedSquare
- Component Value
self.boardState.lastTo- Value
clickedSquare
- Component Value
self.boardState.selected- Value
''
- Custom Event
moveMade
data('Position', clickedSquare, 'side') == self.boardState.sideToMove && clickedSquare != selectedSquarecomparedata('Position', clickedSquare, 'kind') != "" && clickedSquare != selectedSquare- Component Value
self.boardState.selected- Value
clickedSquare
- from
clickedSquare
- from
clickedSquare
- Component Value
self.boardState.selected- Value
''
- Custom Event
positionChanged
Three things change. A Piece may be selected only when it belongs to the Side to move. Keep Safe Moves follows Find Moves. And a Move is made by Move Piece, then announced with moveMade, so Start Turn hears it at once.
Start with the four Set Data Cells, steps 6 to 9 on Chapter 2’s card. Right-click each one and choose Delete.
The card numbers its steps the way the finished game has them, with Move Piece first. Your line will hold the same steps in another order, because a new block joins the end of its line. So steps 6 and 10 go after Clear Targets. Add each with the first If’s Add Inside Then, starting with Move Piece: selectedSquare in from, clickedSquare in to. Then add Trigger Custom Event on Object, with moveMade. It has no Applies to line on the card, so it rings the bell for the Game Rules alone. Your Then line reads 7, 8, 9, 11, 6 and 10.
Does the order matter here? Only in one place, and your line already has it right. Move Piece must come before moveMade, so Start Turn sees the Move. Chapter 4 shows a way to put a step in the middle of a line, for the times the order matters more.
Step 13’s condition changes next. On the card, the new words are green, with the old ones struck under them. Its first test becomes data('Position', clickedSquare, 'side') == self.boardState.sideToMove, and the && clickedSquare != selectedSquare after it stays. Click its box and type the whole condition as the card has it. Last, Keep Safe Moves follows step 15, Find Moves. Add it with the inner If’s Add Inside Then, with clickedSquare in its from.
Run the game, and click a Black Pawn first. Nothing lights, because it’s White’s Turn. Play e2 to e4, and click a White Pawn this time. Nothing lights now either, because the Turn has passed to Black.
Move Black’s f7 Pawn to f6. Click White’s Queen on d1 next, and h5, diagonally out past the e2 Square the Pawn left. Under the Board, the words change: Check. Black’s King on e8 is attacked down the diagonal, h5, g6, f7, e8.
Click Black’s a7 Pawn. Its Square turns gold, but no dot shows. a6 and a5 would leave the King attacked. Click g7. One dot, on g6. That’s the only Move that saves the King.
The words say Check, but nothing on the Board shows which King. The last part does.
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.
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.
Any Objectself.squareInfo- Alpha
0
self.squareInfo.name == other.boardState.lastFrom || self.squareInfo.name == other.boardState.lastTo- Value
@self.lastMoveColor
- Alpha
@self.lastMoveAlpha
self.squareInfo.name == other.boardState.selected- Value
@self.selectedColor
- Alpha
@self.selectedAlpha
self.squareInfo.name == other.boardState.checkSquare- Value
@self.checkColor
- 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.
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.
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.
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.
