A downloadable game

Title: Yep it's more skiing (YIMS)

  Platform: Unexpanded Commodore VIC-20

     Video: PAL/NTSC

 Interface: Keyboard only (n=left, m=right)

 Game type: Arcade

Written by: E W de Villiers

The Plot: 


You won a beauty competition and thereby the accompanying grand prize of a skiing holiday at an exclusive ski resort - YIPEE! After two days of skiing and  sitting in front of a cozy fireplace with hot chocolate in the evenings, you develop an aggravated case of boredom. So the following day you start looking for a challenge and lo and behold you have now found one: The ski slope called 'The Devil's Run'. This slope has been closed for a long time due to excessive injuries and accidents. You obviously ignore all warnings and have decided to attempt the run. Can you guess how this will end?



ski left / ski right = n / m

press any keyboard key to restart the game

For each VIC-20 moment of survival you gain one point. For every flag you manage to capture you receive ten points. Try to obtain the highest score possible so that you can experience a warm glow of satisfaction as you recover in your hospital bed after the inevitable ski crashes.


-------------------------------------------------------------------------------- <- 80 Character line limit
0 fOi=0to47:rEd:pO7168+i,d:pO7424+i,0:nE:v=36864:pOv+5,255:?cH(147):pOv+15,25
1 w=38400:q=7680:x=11:k=28:?cH(19);:fOi=1to22:?cH(17);:nE:?cH(144);:pOv+14,12
2 e=int((rN(0)*3)+66):j=int(rN(1)*19):?"e";sPj);cH(e);sP18-j);"e"
3 l=k:k=pE(197):b=250-(l=36):pOv+12+1,b:ifk<>36andk<>28thenk=l
4 x=x-(k=36)+(k=28):t=-(k=36):c=pE(q+x+22):pOw+x,0:pOq+x,t:ifc=32thens=s+1:gO2
5 ifc=3thens=s+10:fOi=234to254:pOv+10,i:nE:pOv+10,0:gO2:dA 0,10,117,122,28,40
6 h=-s*(s>=h)-h*(s<h):pOv+15,8:?cH(147);cH(18);cH(5);"sc:";s;sP6);"hi:";h
7 pOv+12+1,0:fOi=240to100step-9:fOj=0to9:pOv+10,i+j:nE:nE:wA197,64,64
8 s=0:reS:gO0:dA 80,32,0,80,174,94,56,20,10,4,16,40,16,84,56,146,124,16
9 dA 0,96,88,70,88,96,64,64,84,40,186,84,56,18,71,224,0,0,0,126,86,106,126,195
-------------------------------------------------------------------------------- <- 80 Character line limit

Variables used within the program:


v = constant that holds the Video Interface Chips (VICs) start address in memory which is: 36864

w = constant that holds the start address in memory of the color RAM which is: 38400

q = constant that holds the start address in memory of the video RAM which is:  7680

i = variable used as a general counter for 'for' loops

j = variable used as a general counter for nested 'for' loops.

    also used as a temporary variable to store the offset of obstacles

d = variable used for Read statements to populate the custom character set

x = variable used to store the players column position (X)

k = variable used to store the players keyboard input

e = variable used to store the generated obstacle for the player (tree=66,flag=67,tree with rocks=68)

t = variable used to store the players character (0=left facing,1=right facing)

c = variable used for collision detection of the player with objects

b = variable used to hold the value of the ski sound

s = variable used to store the players score

h = variable used to store the hi score




LINE: 0 for i= 0 to 47: read d: poke 7168+i,d: poke 7424+i,0: next: v=36864: poke v+5,255: print chr$(147): poke v+15,25

poke v+5,255 - This moves the memory pointer for character memory to start at location 7168 in RAM. This now allows the making of custom 8x8 characters.

fori=0to47:readd:poke7168+i,d:poke 7424+i,0:next - This line reads the data statements for six characters (48 bytes) and places them into character memory. The same 'for' loop is also used to clear character memory for the 32nd character (space) which starts at location 7424 = 7168 + 32*8. The five characters that follow are also cleared but this is redundant. This is done to save making another 'for' loop.

v=36864 - this sets v to the start of the VIC registers

print chr$(147) - clears the screen

poke v+15,25 - makes the screen and border white


LINE: 1 w=38400: q=7680: x=11: k=28: print chr$(19);: for i = 1 to 22: print chr$(17);: next: print chr$(144);: poke v+14,12

w=38400 - sets w to the start of color memory

q=7680  - sets q to the start of screen memory

x=11    - sets x to players horizontal (column) position

k=28    - sets k as a default for keyboard input. the key 'n' is 28 and is set as the default, in other words when a game start the player veers left.

print chr$(19); - set the cursor to home (top left)

for i = 1 to 22: print chr$(17);: next - move the cursor down 22 rows

print chr$(144); - set the cursor to black

poke v+14,12 - set the sound volume to 12


LINE: 2 e=int((rnd(0)*3)+66): j=int(rnd(1)*19): print "e";spc(j);chr$(e);spc(18-j);"e"

e=int((rnd(0)*3)+66) - generate a random number between 66 and 68

j=int(rnd(1)*19) - generate a random number between 0 and 18

print "e";spc(j);chr$(e);spc(18-j);"e" - print the barrier character at the start of the next line, place an obstacle at random offset 'j' and then print another barrier character on the right hand of the screen. There is no semicolon after the print statement which causes the screen to scroll one line upwards.


LINE: 3 l=k: k=pE(197): b=250-(l=36): pOv+12+1,b: ifk<>36andk<>28thenk=l

l=k - store the previous (old) keyboard input value in l

k=pE(197) - scan the raw keyboard input value

b=250-(l=36) - depending on whether the player has pressed left or right, update ski sound variable value

poke v+12+1,b - write the ski sound variable to the VIC noise voice register - in other words - make the ski sound for left or right. Why v+12+1 and not just v+13? I have a problem with the number 13 in my code and I avoid using it like the plague. For interest sake: I understand the superstition about the number harkens all the way back to the Babylonians. They based a lot of their number groupings on 12 and we use a lot of 12s in our civilization even today: 12 months in a year, 12 hours separating am and pm, 12 divisions of 5 minutes (see an analog clock face) in an hour and so on. So the number 13 being a prime number and one unit after a dozen (12) unnerved the Babylonians. Unfortunately it unnerves me as well. The Babylonians also appreciated the number 60.

ifk<>36andk<>28thenk=l - if any other key is pressed except for left(n) or right(m) then keep the old direction as the current ski direction


LINE: 4 x=x-(k=36)+(k=28): t=-(k=36): c=peek(q+x+22): poke w+x,0: poke q+x,t: if c=32 then s=s+1: goto 2

x=x-(k=36)+(k=28) - ‘x’ is the new location of the player. (k=28) - if 'k' (which is the value of the key press) is 28 ('n') then add one position to the player position. (k=36) - if 'k' (which is the value of the key press) is 36 ('m') then subtract one position from the player position

t=-(k=36) - t is the ski character which is facing either left (character 0) or right (character 1) depending on what key (k) is pressed

c=peek(q+x+22) - this is the collision detection variable. It stores the value of the screen character right below the player character. Why not rather check diagonally left and right below the player, wouldn't that make the collision detection more accurate? Yes it would but it would also detract from the complexity of skiing. High speed skiing should not be a pushover, just as it isn't a pushover in real life :)

poke w+x,0 - make the color of the player character at the new location black

poke q+x,t - draw the player character (t) at the new location either facing left or right

if c=32 then s=s+1: goto 2 - if the collision detection character is a blank (32), then add one to the score and then goto 2 (the beginning of the core program loop)


LINE: 5 if c=3 then s=s+10: for i=234to254: poke v+10,i: next: poke v+10,0: goto 2: data 0,10,117,122,28,40

if c=3 then s=s+10 - if the collision detected character is a flag character(3) then add 10 points to the score. If the 'if' statement evaluation was TRUE then execute all the statements on the line until carriage return is encountered.

for i=234to254: poke v+10,i: next - make a short sound if the a flag has been encountered (v+10 = voice 1)

poke v+10,0 - silence voice 1

goto 2 - jump back to the start of the main program loop (line 2)

See line 9 for an explanation of the Data statements


LINE: 6 h=-s*(s>=h)-h*(s<h): poke v+15,8: print chr$(147);chr$(18);chr$(5);"sc:";s;spc(6);"hi:";h

if both 'if's in line 4 and 5 were false it means that neither an empty space nor a flag was detected. Oh no, a crash has occured! Now line 6 and 7 is going to execute.

h=-s*(s>=h)-h*(s<h) - This calculates the high score, so let me show you by example:

  A Breadcrumb: A FALSE evaluates to 0. A TRUE evaluates to -1

  Why -1 and not 1? Because VIC Basic logic evaluation is returning results in the format called 2s complement.


  Example 1: The score is 100, the high score is 150

  This evaluates to: h=-100*(0)-150*(-1)=150


  Example 2: The score is 200, the high score is 100

  This evaluates to: h=-200*(-1)-100*(0)=200

poke v+15,8 - Turn the screen and border black

print chr$(147);chr$(18);chr$(5);"sc:";s;spc(6);"hi:";h - clear the screen and print the score and high score in white. One can lookup the chr$ codes in the VIC Programmers reference guide, Appendix F, page 272. 


LINE: 7 poke v+12+1,0: for i=240 to 100 step -9: for j=0to9: poke v+10,i+j: next: next: wait 197,64,64

poke v+12+1,0: for i=240 to 100 step -9: for j=0to9: poke v+10,i+j: next: next - This line uses a nested loop to make a sound. Also there's that number 13 (12+1) again so refer to line 3 for a full explanation of my superstition. Final note: Any value below 128 sent to a VIC-20 sound register results in silence. So as 'i' drops below 128 the voice mutes.

wait 197,64,64 - Monitor memory location 197 for a change. This checks the keyboard matrix for 64 (no key press) through the first parameter which ANDs (filters) 64. The second parameter is an XOR which means the moment a key is pressed the 64 bit is flipped, the status changes and the wait is over (See P34 of the programmers reference guide). In short: If a key is pressed then continue otherwise keep waiting.


LINE: 8 s=0: restore: goto 0: data 80,32,0,80,174,94,56,20,10,4,16,40,16,84,56,146,124,16

Most Vic-20 10 liners use the command 'run' to reset all the variables and to allow for 'read' statements to be executed again without an 'out of data' error. It also restarts execution from the first basic line of code again. However because the game has a high score one cannot just reset all the variables. So the score variable has to be reset manually with s=0 and then a 'restore' command has to be executed to allow the 'read' statement to read data statements from the beginning (in other words it resets the read pointer). That is then followed with a goto 0 which essentially restarts the program with the high score still intact.


LINE: 9 data 0,96,88,70,88,96,64,64,84,40,186,84,56,18,71,224,0,0,0,126,86,106,126,195

All the data statements in line 5,8 and 9 are the data for the six custom characters (8 bytes per character x 6 characters = 48 bytes)



yims-unexp.d64 170 kB
yims-unexp.prg 687 bytes
yims-unexp.t64 1 kB
YIMS-VIC20 unexpanded.pdf 844 kB
YIMS-VIC20 unexpanded.txt 12 kB

Install instructions



Real unexpanded VIC-20 with a tape system:

1. Type load and then press return 2. Type run and then press return

Real unexpanded VIC-20 with a disk system:

1. Type load "*",8 and then press return 2. Type run and then press return

On an emulator:

Copy the source code in this document and paste it into an opened VIC emulator with no expansion RAM. Then in the emulator type run and then press enter. OR

Drag and drop the yims.prg file into an opened VICE emulator.


Huffelduff (User handle on the VIC-20 Denial forum)


Log in with itch.io to leave a comment.

very good