Rock
Paper
Scissors

The game of Rock, Paper, Scissors .  .  .
using a micro.

Page 1          Page 2





This program has been written for PIC LAB-1 and requires no extra components. 
The files are in: 
RPS files

The game of Rock, Paper, Scissors has always fascinated me. 
It's so simple. 
The clever part is the rotary nature of the output. 
Rock breaks scissors, Paper covers Rock and Scissors cuts Paper. 
The first in each result always wins. 
There are over 100 websites devoted to this game. 
It has quite a cult following. 
Some of the websites have an animated representation of the action of the game. 
If you don't know how to play it, HERE is a FLASH demonstration and HERE is another version you can play as an opponent.
There are also long-page-articles on the subject.

We cannot produce anything like the complexity of the internet presentations as we are working with one of the simplest microcontrollers, however we can show how to put a program together to produce almost any effect on a row of LEDs and 7-segment display. 
The RPS program does not contain any strategy or "thinking" but it can be designed for effect. 
The three letters on the 7-segment show "R P S" to indicate Rock, Paper, Scissors. This is the simple part. The lead-up to this involves flashing the 8 LEDs.
There are 3 different sections of the program:
1. The 8-LED display
2. The random number generator
3. The overall sequencing of the program. 

The 8 LED display can produce a number of effects such as "running,"  "flashing" or "splitting" and the 7-segment display can produce almost all the letters of the alphabet.
The results on the screen need to be random and this can be achieved by a random number generator, a table or by human intervention. 
We will be making the program run automatically and thus a random number produced by human intervention will not be possible. 
As you will see in a moment, computers are not capable of producing truly random numbers and so the solution is to have a long list of numbers in a table and the micro increments down the list. 
The overall sequencing of the program is a TIMING issue. Its just a matter of producing a suitable delay for each effect and running through it at the right speed.  

RANDOM NUMBERS
Computers are not very good at producing random numbers. 
There is nothing in a microcontroller that can be used to produce an unknown number ON A REGULAR BASIS. 
If the program is allowed to run automatically, it would be difficult to generate a random number by looking at the contents of a set of files, for example. You have no guarantee of getting an "even spread of results".
On the other hand, if you produce a table, the spread can be absolutely even or a slight advantage can be introduced. 
Even the smallest "odds" can reap an enormous reward. 
Casinos are supposed to have a "house advantage" of only a few percent, and on the roulette table it is about 3%. 
Suppose this "advantage" is transferred to a "poker machine".  It simply means you will lose all your money for every 33 plays!
It's simple mathematics. There are times when you win, but this simply increases the number of "plays" before you lose everything.
The longer you play, the more guarantee you have of losing EVERYTHING. 
It's an absolute certainty. 
Mathematic doesn't lie. 
The table used in our RPS game is not "weighted" and theoretically you should win exactly 50% of the time. 
This is a good predictor of human behaviour. 
Everyone thinks they can "beat the odds" and predict an event with a result better than 50%. 
This is incorrect. Humans are not as good as 50%. They average about 45%. That's why the average winnings on a table is about 5%. 
Take the RPS game. Play it 100 times and see the result. It's a perfect challenge .  .  .

CHIPS
The complexity of this game would require at least 6 chips if using older-style circuitry. The overall cost would be higher than a micro design and development time would be substantially greater. 
With our design, additional features can be added very easily and at very little cost, whereas a project made with discrete components would require complete re-designing.  
There is really no comparison, however some readers still need convincing of the enormous advantages of designing a project around a micro. 
If you are still working your way through the routines, try reading them exactly how the micro interprets them. They have been presented in a layout called "linear," with very few jumps up and down the page. All the files and values are visible so you can see exactly what is going on.  It's as clear as we can possibly make it. 
Any programs you produce can be designed along similar lines. They don't have to be "high technology." Go through the programs we have already presented. They will help you get a program together much faster than doing it all yourself.

THE SUB-ROUTINES
When writing a program, individual sub-routines are created in any order, as you think of them, and placed in the program in alphabetical order. Only write the code when you have the inspiration to create it.
For each sub-routine, a result must be generated and placed in a flag file or in a file that is not used by any other sub-routine. Don't branch-off from a sub-routine to another sub-routine. Go back to main and use the result from the sub-routine or flag file. 
If you need to do another calculation or produce another effect, write CALL xxxx instruction in Main. Go to the sub-routine, carry out the instructions and return to Main.
Each sub-routine must have a RETURN to Main. 
If a sub-routine increments a file, you must be sure the file has been incremented only once otherwise the result will be incorrect.  
These are the main requirements.

THE PROGRAM 
The first effect on the display is called the "attract" mode. This draws the player to the game. In our version the "Attract Mode" is similar to "Split," where the LEDs are removed from the middle until all are removed. The action is then reversed. 
Push button "A" to start the game. 
The display will produce a random effect and then a letter on the screen. 
The screen shows the letter for about 3 seconds and the cycle repeats. 
Compare the choice you make (rock, paper, scissors) with the display and work out the winner. 
The program can be extended by allowing the button to be pressed one, two or three times for rock, paper or scissors and this will be recorded. The display will show the score after say 20 games. 
Each sub-routine is very easy to follow.  No complex instructions have been used. 
But a few clever ideas have been introduced, such as . . .
1. In the Attract sub-routine, to put FF into a file, it is cleared and decremented. 
2. In the Run sub-routine, the RRF and RLF instructions move a bit across the display and back again. To detect when a bit has "fallen off the end of a file," the carry bit is tested.  
3. Before each letter appears on the screen, an effect, such as "Flash," "Run," or "Toggle," appears on the 8 LEDs. Both the "effect" and one of the letters is determined by a random number table. To prevent the effect coinciding with the letter on the screen, the jump value for the effect is incremented twice in the Display sub-routine. To detect this double-jump, the end of table needs two FF values.  
4. To test for End of Table, bit 7 is tested. Any bit above bit 2 can be tested in our case, we have used bit7 for convenience. There are three values in the random number table. To test these three values, bits 0, 1 and 2 have been used. This allows bit-testing. Bit0 = 0000 0001=1 , bit1 = 0000 0010=2 and bit 3 = 0000 0100=4. Bit testing is the easiest way to identify three values.

                    ;RPS-1.asm
                    ;Project: Rock Paper Scissors
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC

SetUp









Table















































Attract





























Delay1

DelA




Del300

DelB





Del100

Del101









Display





















Flash

Flash1












Run

RunA

Run1




Run2
Run3











Toggle

Toggle1













Main


MainA






MainB



Main2



Main3
Main4


MainC




MainD





Main5





Main6


ORG 0 
BSF 03,5 
MOVLW 03 
MOVWF 05 
CLRF 06 
BCF 03,5 
CLRF 1C 
CLRF 1D 
CLRF 1F 
GOTO Main

ADDWF 02h,1 
RETLW 04h    
RETLW 01h    
RETLW 02h  
RETLW 02h 
RETLW 04h 
RETLW 04h 
RETLW 02h 
RETLW 01h 
RETLW 02h 
RETLW 01h 
RETLW 04h 
RETLW 02h 
RETLW 04h 
RETLW 02h 
RETLW 01h 
RETLW 04h 
RETLW 04h 
RETLW 01h 
RETLW 01h 
RETLW 04h 
RETLW 02h 
RETLW 01h 
RETLW 02h 
RETLW 01h 
RETLW 04h 
RETLW 02h 
RETLW 04h 
RETLW 02h 
RETLW 02h 
RETLW 01h 
RETLW 04h 
RETLW 02h 
RETLW 04h 
RETLW 02h 
RETLW 01h 
RETLW 04h 
RETLW 04h
RETLW 01h 
RETLW 01h 
RETLW 04h 
RETLW 02h 
RETLW 01h 
RETLW 0FFh 




CLRF 06
DECF 06,1 
CALL Del100
MOVLW 0E7h
MOVWF 06
CALL Del100 
MOVLW 0C3h
MOVWF 06
CALL Del100 
MOVLW 81h
MOVWF 06
CALL Del100 
CLRF 06
CALL Del100 
MOVLW 81
MOVWF 06
CALL Del100 
MOVLW 0C3h
MOVWF 06
CALL Del100
MOVLW 0E7h
MOVWF 06
CALL Del100 
CLRF 06
DECF 06,1 
CALL Del100 
CLRF 06
RETURN


MOVLW 0A
MOVWF 10h
CALL Del100
DECFSZ 10h,1
GOTO DelA
RETURN

MOVLW 03
MOVWF 10h
CALL Del100
DECFSZ 10h,1
GOTO DelB
RETURN


MOVLW 64h 
MOVWF 1B
NOP
DECFSZ 1A,1
GOTO Del101
BTFSC 05,0
BSF 1F,0 
DECFSZ 1B,1
GOTO Del101
RETURN


MOVF 0Eh,0
MOVWF 06
CALL Del100
CLRF 06
CALL Del100 
MOVF 0Eh,0
MOVWF 06 
CALL Del300
CLRF 06
CALL Del300
MOVF 0Eh,0
MOVWF 06
CALL Delay1
CALL Delay1
CALL Delay1
CALL Delay1
CLRF 06
CALL Delay1
INCF 1C,1
INCF 1D,1
RETURN

MOVLW 04
MOVWF 1E
CLRF 06 
CALL Del100
CALL Del100
DECF 06,1 
CALL Del100
CALL Del100
DECFSZ 1E,1
GOTO Flash1
CLRF 06
RETURN 



MOVLW 04
MOVWF 1E
CLRF 06
INCF 06,1 
RLF 06,1
BTFSC 03,0 
GOTO Run2 
CALL Del100 
GOTO Run1
RRF 06,1 
CALL Del100 
RRF 06,1 
BTFSS 03,0 
GOTO Run3 
DECFSZ 1E,1
GOTO RunA
CLRF 06
RETURN 




MOVLW 04
MOVWF 1E
MOVLW 0F0h
MOVWF 06 
CALL Del300 
MOVLW 0Fh
MOVWF 06 
CALL Del300 
DECFSZ 1E,1
GOTO Toggle1
CLRF 06
RETURN




CALL Attract
BTFSS 1F,0
GOTO Main
MOVF 1C,0 
CALL Table
MOVWF 11h 
BTFSS 11h,7 
GOTO MainB
CLRF 1Ch
GOTO MainA
BTFSS 11h,0
GOTO Main2
CALL Flash 
GOTO Main4
BTFSS 11h,1
GOTO Main3
CALL Run 
GOTO Main4
CALL Toggle
CALL Delay1  
MOVF 1D,0 
CALL Table
MOVWF 12h 
BTFSS 12h,7 
GOTO MainD
CLRF 1D
GOTO Main4
BTFSS 12h,0
GOTO Main5
MOVLW 33h 
MOVWF 0E 
CALL Display
GOTO MainA
BTFSS 12h,1
GOTO Main6
MOVLW 73h 
MOVWF 0E 
CALL Display
GOTO MainA
MOVLW 6Dh 
MOVWF 0E 
CALL Display
GOTO MainA

END 
;Start of memory for the program.
;Go to Bank 1  >
;Load W with 0000 0011
;Make RA0, RA1 input
;Make all port B output
;Go to Bank 0 - the program memory area. 
;Clear the jump counter
;Clear the jump counter
;Clear the button-press file


;Add W to Program Counter to create a jump.
;4
;1
;2
;2
;4
;1
;2
;1
;2
;1
;4
;2
;4
;2
;1
;4
;4
;1
;1
;4
;2
;1
;2
;1
;4
;2
;4
;2
;2
;1
;4
;2
;4
;2
;1
;4
;4
;1
;1
;4
;2
;1
;End of table

;"Attract" Attract removes the LEDs from the middle of ;the display and continues until all LEDs are removed, then reverses.
;Clear the output 
;Make the output file FFh.  Illuminate all LEDs
;Call 100mS delay
;Remove the two centre LEDs
;Output the result
;Call 100mS delay
;Remove the 4 centre LEDs
;Output the result
;Call 100mS delay
;Remove the 6 centre LEDs
;Output the result
;Call 100mS delay
;Remove all the LEDs
;Call 100mS delay
;Display only the two outer LEDs
;Output the result
;Call 100mS delay
;Display the 4 outer LEDs
;Output the result
;Call 100mS delay
;Show all LEDs except the two centre LEDs
;Output the result
;Call 100mS delay

;Illuminate all LEDs
;Call 100mS delay
;Clear the display



;1 second delay














;100 loops = 100mS











;File 0E will have output value for 7-segment display
;Display the value
;Call 100mS delay to flash value on screen
;Clear display
;Call 100mS delay
;Show value again for 300mS


;Clear display

;Show value on screen for 4 seconds





;Clear screen

;Increment the jump-value for the "effect"
;Increment the RPS value

;"Flash" Flashes all 8 LEDs on the display 4 times. 
;then RETURNs to Main

;Zero file 6  Turn off all LEDs
;Delay for 100mS
;Delay for 100mS
;Make file 06 = FF Turn on all LEDs
;Delay for 100mS
;Delay for 100mS
;Decrement the loop counter




;"Run" produces a Running LEDs effect across the
;display. The Running bit is stored in file 0D. It moves
;across and back 4 times then RETURNs to Main


;Create "bit"
;Move the "bit" to the left
;Test the carry bit

;100mS delay

;Move the bit back onto the display
;100mS delay
;Move the "bit" to the right
;Test the carry bit

;Decrement the loop counter





;"Toggle" Flashes the top 4 LEDs then the bottom 4
;LEDs. This is repeated 4 times
;Create 4 loops
;Put 4 into loop counter
;Display top 4 LEDs
;Turn on 4 top LEDs
;Show for 300mS
;
;Turn on 4 bottom LEDs
;Show for 300mS
;Decrement the loop counter

;Clear the screen before leaving


;File 1C = jump value for "Attract" sub-routine before
;displaying RPS.  File 1D = jump value for RPS value




;Copy 1C to W

;File 11h holds 1, 2, 4 or FF
;Test for End of Table

;End of table reached. Start at top 

;See if effect is "Flash"



;See if effect is "Run"



;Effect is "Toggle."
;Call 1 second delay
;Copy 1D to W

;File 12h holds 1, 2 or 4
;Test for End of Table





;Produce "R"
;Put display value into file 0E




;Produce "P"
;Put display value into file 0E


;Produce "S"
;Put display value into file 0E



;Tells assembler end of program

GOING FURTHER
The program can be extended in many ways. 
On the next page we will extend the program to include input from the player. 

 

To Top