Documention for: nim-engine.r Created by: sunanda on: 19-Jul-2005 Format: text/editable Downloaded on: 30-Apr-2025 [contents [numbering-on [asis Sunanda July 2005 asis] [h2 NIM Engine [p This script does two things: [li Plays a game of NIM under any version of REBOL Core. Pretty basic, as it uses the command line for input and output; [li Provides a complete API for any more graphic game you might want to write that uses NIM as part of its strategy. list] [h2 NIM [p NIM is one of those simple games that, if you know the simple rule of success, makes you almost unbeatable. If you don't, it is highly frustrating. [p The rules are simple. [li Two people play [li Start with several piles of counters [li Each player takes it in turn to take as many counters as they like from any **one** pile [li The player who takes the last counter wins [li or, as a variant, the player who takes the last counter wins. NIM-engine will play both versions. list] [p A classic starting position is : [table/att/border=1/style/border:thin+blue+solid/att/width=30%/style/text-align:center [cell Pile 1 [cell Pile 2 [cell Pile 3 [row [cell 3 [cell 4 [cell 5 table] [p The only winning move (whichever variant you are playing) is to take 2 counters from Pile 1, leaving: [table/att/border=1/style/border:thin+blue+solid/att/width=30%/style/text-align:center [cell Pile 1 [cell Pile 2 [cell Pile 3 [row [cell 1 [cell 4 [cell 5 table] [h3 Variants and terminology [li **common** game -- you lose if you take the last counter [li **straight** game -- you win if you take the last counter list] [h2 Playing the built-in game [asis do %nim-engine.r nim-engine/play-game asis] [p nim-engine will generate a random starting position, and ask you to move. [p By default, this is the **common** game: you lose if you take the last counter. [h3 Game variants [p To play the **straight** game (win if you take the last counter): [asis nim-engine/play-game/type "straight" asis] [h3 Play from a given position: [p If you want to specify a starting position: [asis nim-engine/play-game/position [5 5 1 3] asis] [h3 Make nim-engine play first: [p If you want nim-engine to play first from a random starting position [asis nim-engine/play-game/opponent-starts asis] [p If you want nim-engine to move first from a specified starting position: [asis nim-engine/play-game/opponent-starts/position [5 5 1 3] asis] [h2 Using the API [p You can use nim-engine.r as a hidden asset in nim-like games you write. [p To do that, there is simply one call you need to use: [asis nim-engine/move "common" [3 4 5] asis] [p You supply: [li the game type as a string [li the current game position list] [p nim-engine returns an object containing the move to make and some status information: [asis probe nim-engine/move "common" [3 4 5] make object! [ game-type: "common" game-over?: false winner?: none move: 1x2 piles: [1 4 5] winning?: "nim-engine" ] asis] [table/att/border/"1" [cell **game-type** [cell reflects back the input field [row [cell **game-over?** [cell true/false depending on whether more moves are possible [row [cell **winner?** [cell who won (""human"" or ""nim-engine"") if the game is over -- see below for more details [row [cell **move** [cell (assuming the game wasn't over when you made the call) the move nim-engine is making. A pair: 1x2 means taking 2 from pile 1 [row [cell **piles** [cell the updated position block [row [cell **winning?** [cell which player is winning table] [h3 Player names [p nim-engine/move assumes each time you call it you are asking it to make a move. [p Which is fine if you are mediating a game between the computer and a human. But may be confusing if you are handling two humans calling each other, or tow computers. [p If so, it may help to supply the player names: [asis >> probe nim-engine/move/names "straight" [0 0 8] ["Cindy" "Carl"] make object! [ game-type: "straight" game-over?: true winner?: "Cindy" move: 3x8 piles: [0 0 0] winning?: "Cindy" ] asis] [h2 Test driver [p If you make changes to this code -- or just want some confidence that it is right, use the build-in test driver: [asis do %nim-engine.r nim-engine/test-driver asis] [p nim-engine will start playing a series of random games with itself, reporting every 100 on the console. [p After each move, it analyses the move made and the resultant piles to see if they make sense. If they don't, it reports the anomaly. Any anomaly means that something has gone wrong -- nim-engine has made an invalid move, or corrupted the piles block. [p To change the default number of piles and their maximum sizes in the games the test driver runs, find and edit this line: [asis loop 5 + random/secure 5 [append piles random/secure 20] asis] [p (that default lines means each random game starts with 5 to 10 piles each with up to 20 counters) [p [date [link http://www.rebol.org/cgi-bin/cgiwrap/rebol/documentation.r?nim-engine.r "Nim-engine.r Documentation"