One CommVEx Peeve

Of all the things about CommVEx I have one “PET” peeve (well pet peeve, but couldn't stop thinking about the Commodore PET) that has bugged me (and from mutterings, a couple other folks share in the frustration). It is the doorprize program. I love the idea that the program is ran on the Commodore, I like that the computer randomly chooses… but.. I've noticed (like most random programs) it favors the center of the distribution and also can pick the same person twice… (unless you keep the program running… which isn't feasible).

So one of my self-inflicted projects is to make a 21st century doorprize drawing program for the 64.

RANDOM DRAW v.07

Well that's the working name. This is about version .7 as not all the features or interface has been implemented, but enough where it could be put to work right now.

Let me go over the features so far:

Heres my code so far:

{renumber}
{alpha:upper}
{number:10}
{step:10}
rem *** random draw ***
rem by larry anderson v.07 9/25/2011
rem designed to have a non-repeating random door prize draw
rem which includes tracking of winners
rem with the ability to save/load draws in progress
rem ==========
rem formatted for C64list by Jeff Hoag
rem conversion command:  C64List randomdraw.txt -prg:random.prg
rem 
poke 53280,15:poke 53281,0:print"{white}{clear}"
print "random drawing program - by larry anderson 9/2011"
gosub {:initvars}
{:mainmenu}
    print "{rvrs on}draw menu---------{rvrs off}
    print " 1 - draw prize"
    print " 2 - list names"
    print " 3 - list winners"
    print " 4 - add names"
    print " 6 - load data"
    print " 7 - save data"
    print " 8 - produce report"
    print " 0 - reset draw stats"
    print " q - quit program"
    print "enter option:";:inputm$
    ifm$="1" then gosub {:drawprize}
    ifm$="2" then gosub {:listnames}
    ifm$="3" then gosub {:listwinners}
    ifm$="4" then gosub {:addnames}
    rem ifm$="5" then gosub
    ifm$="6" then gosub {:diskload}
    ifm$="7" then gosub {:disksave}
    ifm$="8" then gosub {:makereport}
    rem ifm$="9" then gosub
    ifm$="0" then gosub {:resetdraw}
    ifm$="q" then gosub {:endroutine}
goto {:mainmenu}
end

{number:500}
{:endroutine}
    ifdc%=0 then goto {:endroutine1}
    print "!!!!!data has not been saved, exit anyway? (y/n)";
    input q$
    if q$<>"y" then print "exit aborted.":return
{:endroutine1}        
end

{number:1000}
{:initvars}
rem *** initialize variables ***
    rem arrays - names, current draw status, prize names, prize winners, temp
    dim nm$(200), dr%(200), pz$(100), pw%(100), tp%(200)
    nn%=0: nw%=0: rem number of names, number of winners
    dv%=peek(186):fi$="namefile":rem default device and file name
    dc%=0:rem data change flag if 1, data has changed since last save.
return

{number:1500}
{:drawprize}
    print "{rvrs on}draw for prize{rvrs off}"
    print "   options: yes/no/reset list/cancel"
    print "            (y/n/r/c)"
    if nn%=0 then print "!-no names in database":return
    gosub {:getdrawlist}:rem *** get draw list
    rem *** if all have been drawn, reset draw list
    if tc%=0 then rd%=1:gosub {:getdrawlist} 
    if tc%=0 then print "!-no eligible names to draw":return
{:drawprize1}
    rem *** select randome winner ***
    wn% = int(rnd(1)*tc%)
    rem confirm winner?
    print "from "+str$(tc%)+" names; ";
    print "is "+nm$(tp%(wn%))+" present ";:input a$
    if a$="y" then goto {:drawprize2}
    if a$="r" then rd%=1:gosub getdrawlist:goto {:drawprize1}
    if a$="c" then return
    print "!-name not selected... redraw":goto {:drawprize1}
{:drawprize2}
    print "enter prize won: ";:input pn$
    rem record changes
    dr%(tp%(wn%))=1:pw%(nw%)=tp%(wn%):pz$(nw%)=pn$:nw%=nw%+1:dc%=1
return

{number:2000}
{:listnames}
    print "participant list:"
    for x=0to nn%-1
        print str$(x+1)+" "+nm$(x);
        if dr%(x)=2 then print " {red}(win disabled){white}";
        if dr%(x)=1 then print " {yellow}(selected this round){white}";
        print
    next x
    print "=========="
return

{number:2500}
{:addnames}
    print"{rvrs on}add new participants{rvrs off} enter zz to exit"
    print"enter name, short with no commas or quotes:"
{:addnames1}
    print"enter name: ";:input n$
    if n$="zz" then goto {:addnames3}
    ifnn%=0then goto {:addnames2}
    ne% = 0
    for x=0to nn%-1
      if nm$(x) = n$ then ne%=1
    next x
    if ne%=1 then print"!-name exists, enter a unique one.":goto {:addnames1}
{:addnames2}
    nm$(nn%) = n$:nn%=nn%+1:print"+-name "+str$(nn%)+" added":dc%=1
    goto{:addnames1}
{:addnames3}
    print "=========="
return

{number:3000}
{:listwinners}
    print "{rvrs on}winners list{rvrs off}"
    for x=0to nw%-1
        print str$(x+1)+" "+pz$(x)+"->"+nm$(pw%(x))
    next x
    print "=========="
return

{number:3500}
{:makereport}
print "report coming soon"
return

{number:4000}
{:resetdraw}
  rd%=1:gosub{:getdrawlist}
  print "{rvrs on}draw list has been reset{rvrs off} "+str$(tc%)+" names eligible.";
return

{number:4500}
{:getdrawlist}
    tc%=0:rem *** reset draw list and get names not already drawn ***    
    for x=0 to nn%-1
      if dr%(x)=1 and rd%=1 then dr%(x)=0:
      if dr%(x)=0 then tp%(tc%)=x:tc%=tc%+1
    next x
    rd%=0
return

{number:5000}
{:disksave}
    rem *** record data to disk ***
    print "device #:  "+str$(dv%)
    print "{up}{right:10}";:input dv%
    print "file name:   "+fi$
    print "{up}{right:11}";:input fi$
    open 15,dv%,15,"s0:rd-"+fi$:close15
    gosub {:errorcheck}
    open 2,dv%,2,"0:rd-"+fi$+",s,w"
    gosub {:errorcheck}
    if e%<>0 then goto {:disksave2}
    rem store number of names and names
    print#2, nn%
    for x=0 to nn%-1
        print#2,nm$(x):print#2,dr%(x)
    next x
    rem store number of winners list and name number
    print#2, nw%
    if nw%=0 then goto {:disksave1}
    for x=0 to nw%-1
        print#2,pz$(x):print#2,pw%(x)
    next x
{:disksave1}
    print#2,"" :rem  extra line for padding.
    gosub {:errorcheck}
{:disksave2}
    close 2
    if e%<>0 then print "!-device error "+e$: goto {:disksave3}
    print "data saved, no errors.":dc%=0
{:disksave3}
return

{number:5500}
{:diskload}
    print "device #:  "+str$(dv%)
    print "{up}{right:10}";:input dv%
    print "file name:   "+fi$
    print "{up}{right:11}";:input fi$
    nn%=0:nw%=0:rd%=0
    rem *** load data from disk ***
    open 2,dv%,2,"0:rd-"+fi$+",s,r":gosub {:errorcheck}
    if e% <> 0 goto {:diskloaderror}
    rem number of names, names and thier current draw status
    input#2, nn%
    for x=0 to nn%-1
        input#2,nm$(x):input#2,dr%(x)
    next x
    rem number of winners and prizes, winner number if winners
    input#2, nw%
    if nw%=0 then goto {:diskload1}
    for x=0 to nw%-1
        input#2, pz$(x):input#2,pw%(x)
    next x
{:diskload1}
    gosub {:errorcheck}
    if e%<>0  then {:diskloaderror}
    print "data loaded sucessfully.":dc%=0
    close 2: return
{:diskloaderror}
    print "!-device error: "+e$
close 2:return

{number:6000}
{:errorcheck}
    open 15,dv%,15
    input#15, e%,e$,t%,s%
    print e%,e$,t%,s%
    close15
return

Nice thing about C64List is that I can do formatting for the non-commodore text version for readability, do search and replace (like when I hit a reserved variable) and scroll about quite easily. Also given that I have more stretching room I am working on saving variable space by using integers when possible, working on good naming and labeling, etc. This also gives me a better “big picture” view to reduce redundancy of common routines. Sill getting a handle on the pseudo op tokens (like changing colors, etc), its pretty straightforward.

Whats next? Better formatting, an option to skip over names (i.e. they were present on the first day, but not on the second, so we want them still listed in history but not considered for the later draws… you will notice I have some code to handle that circumstance already, but nothing to flag them yet). As well as a report producer suitable for printing or as text for a news article. Also it still uses Commodore BASIC's RND function which isn't optimal… that will be enhanced too.

Transfer from Linux to the 64 is via an SD card with a uIEC-SD drive http://store.go4retro.com/products/uIEC_SD.html on the 64 or testing locally in the VICE Commdore emulator http://www.viceteam.org/ in immediate mode.

~~LINKBACK~~ ~~DISCUSSION~~