Moving Players

Before a player can move, you need to ensure that it is a valid move. In the case of this naive implementation of checkers, a valid move is:

  • The “move distance” from current to target (single axis) is valid
  • The target space is unoccupied
  • The piece being moved belongs to the current player

Let’s take a look at the code to determine if a move is valid:

 ;; Determine if the move is valid
 (func $isValidMove (param $fromX i32) (param $fromY i32)
  (param $toX i32) (param $toY i32) (result i32)
  (local $player i32)
  (local $target i32)
 
  (set_local $player (call $getPiece (get_local $fromX) (get_local $fromY)))
  (set_local $target (call $getPiece (get_local $toX) (get_local $toY)))
 
  (if (result i32)
  (block (result i32)
  (i32.and
  (call $validJumpDistance (get_local $fromY) (get_local $toY))
  (i32.and
  (call $isPlayersTurn (get_local $player))
  ;; target must be unoccupied
  (i32.eq (get_local $target) (i32.const 0))
  )
  )
  )
  (then
  (i32.const 1)
  )
  (else
  (i32.const 0)
  )
  )
 )
 
 ;; Ensures travel is 1 or 2 squares
 (func $validJumpDistance (param $from i32) (param $to i32) (result i32)
  (local $d i32)
  (set_local $d
  (if (result i32)
  (i32.gt_s (get_local $to) (get_local $from))
  (then
  (call $distance (get_local $to) (get_local $from))
  )
  (else
  (call $distance (get_local $from) (get_local $to))
  ))
  )
  (i32.le_u
  (get_local $d)
  (i32.const 2)
  )
 )

The code for $validJumpDistance might look a little strange. Since WebAssembly’s integers don’t support the abs function, we’re basically deciding on the order in which we supply arguments to the $distance function based on whether or not it will result in a negative number. Also remember that we’re not building a rules-compliant version of checkers—this is just enough code to exercise some basic rules in service of learning WebAssembly.

In the following code listing, the $move function will eventually be exported (typically done at the end of the module code) function so the host can call it. Since this makes it a public API method, it has to guard against bad data and invalid moves. $move returns 1 for a successful move and 0 for a failed one:

 ;; Exported move function to be called by the game host
 (func $move (param $fromX i32) (param $fromY i32)
  (param $toX i32) (param $toY i32) (result i32)
  (if (result i32)
  (block (result i32)
  (call $isValidMove (get_local $fromX) (get_local $fromY)
  (get_local $toX) (get_local $toY))
  )
  (then
  (call $do_move (get_local $fromX) (get_local $fromY)
  (get_local $toX) (get_local $toY))
  )
  (else
  (i32.const 0)
  )
  )
 )

Notice that the $move function defers some functionality to the $do_move function. This separates the conditional guard checking code from the actual state changes in $do_move. After a move toggles the current turn owner, the state change sets the piece at the destination location, and wipes out the piece at the original location:

 ;; Internal move function, performs actual move post-validation of target.
 ;; Currently not handled:
 ;; - removing opponent piece during a jump
 ;; - detecting win condition
 (func $do_move (param $fromX i32) (param $fromY i32)
  (param $toX i32) (param $toY i32) (result i32)
  (local $curpiece i32)
  (set_local $curpiece (call $getPiece (get_local $fromX)(get_local $fromY)))
 
  (call $toggleTurnOwner)
  (call $setPiece (get_local $toX) (get_local $toY) (get_local $curpiece))
  (call $setPiece (get_local $fromX) (get_local $fromY) (i32.const 0))
  (if (call $shouldCrown (get_local $toY) (get_local $curpiece))
  (then (call $crownPiece (get_local $toX) (get_local $toY))))
  (call $notify_piecemoved (get_local $fromX) (get_local $fromY)
  (get_local $toX) (get_local $toY))
  (i32.const 1)
 )

As a convenience, the $do_move function invokes a function called $notify_piecemoved that lets the host know when a piece has finished moving. This function will be declared as an import at the beginning of the module. This function is called so the host can react to player movement rather than repeatedly polling for changes to the game board state.

Finally, with all the basic functions in place, it’s time to connect this module to a host and test it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.14.118