File "Bookworm.bas"
Path: /Bookworm/Bookworm.bas
File size: 50.38 KB
MIME-type:
Charset: utf-8
% Bookworm v0.3 for RFO-BASIC!
% v0.1 written by Nicolas Mougin in December 2015 [OPEN SOURCE] - For Mom
% v0.2 adapted in multiple languages for the guys at rfobasic.freeforums.org
% v0.3 released in March 2025. Changelog:
% - Fixed touch zones that were incorrectly shifted
% - Fixed welcome audio at first start
% - Download game resources from internet
% - Language selector in apk & editor
% - Add greek and norwegian menus
% Known limitation: pressing Home key during a game animation exits without saving progress
%TODO
% Hall of fame when game over or new game or new language
debug=0 % Activate if you want to test a new menu language
lng$="fr en de gr no ro"
GOSUB Functions % Register custom functions
isAPK=IsApk()
FILE.EXISTS fe, "bookworm.cfg"
IF fe % Get menus and game language from config file + sound setting
TEXT.OPEN r, fid, "bookworm.cfg"
TEXT.READLN fid, mLng$ % menus language
TEXT.READLN fid, gLng$ % game language
TEXT.READLN fid, e$: IF !IS_IN(e$, "01") THEN e$="0"
mute=VAL(e$) % sound setting
TEXT.CLOSE fid
ENDIF
GOSUB CheckResources
GOTO Initialization
%==========================================================
Functions:
FN.DEF IsApk()
FILE.EXISTS editorMode, "../source/Bookworm.bas"
FN.RTN !editorMode
FN.END
FN.DEF Fatal(err$)
IF IsAPK() THEN : POPUP err$ : EXIT : ELSE : END err$ : ENDIF
FN.END
FN.DEF DL(res$)
BYTE.OPEN r, fid, "http://mougino.free.fr/code/Bookworm/"+res$
BYTE.COPY fid, res$
CheckExist(res$)
FN.END
FN.DEF CheckAndDL(res$)
% Check presence of a mandatory file: if absent, download it
FILE.EXISTS fe, res$
IF !fe THEN DL(res$)
FN.END
FN.DEF CheckExist(file$)
% Check presence of a mandatory file: if absent, alert & quit to system
FILE.EXISTS fe, file$
IF !fe THEN Fatal("Fatal error:\n" + CHR$(34) + file$ + CHR$(34) + " not found!")
FN.END
FN.DEF LoadFlag(lng$)
BUNDLE.CONTAIN 1, "lng-"+lng$, ptr
IF !ptr
GR.BITMAP.LOAD ptr, lng$+".jpg"
IF ptr<0 THEN GR.BITMAP.LOAD ptr, lng$+".png"
IF ptr<0 THEN Fatal("Missing '"+lng$+"' image")
BUNDLE.PUT 1, "lng-"+lng$, ptr
ENDIF
FN.END
FN.DEF BmpFlag(lng$)
BUNDLE.GET 1, "lng-"+lng$, ptr
FN.RTN ptr
FN.END
FN.DEF LoadLngN(lng$) % Load language name (how it is called in said language)
BUNDLE.CONTAIN 1, "lngn-"+lng$, ptr
IF !ptr
CheckExist("labels_"+lng$+".txt")
TEXT.OPEN r, fid, "labels_"+lng$+".txt"
TEXT.READLN fid, nm$
nm$=MID$(nm$,6) % "lang=..."
TEXT.CLOSE fid
BUNDLE.PUT 1, "lngn-"+lng$, nm$
ENDIF
FN.END
FN.DEF LngN$(lng$)
BUNDLE.GET 1, "lngn-"+lng$, nm$
FN.RTN nm$
FN.END
FN.DEF LoadPngSeries(png$)
DO
GR.BITMAP.LOAD nul, png$+INT$(i)+".png"
IF nul>0 & !ptr THEN ptr=nul
i++
UNTIL nul<=0
FN.RTN ptr
FN.END
FN.DEF StrSwap(t$, pos1, pos2)
IF pos1>pos2 THEN SWAP pos1, pos2
c1$=MID$(t$, pos1, 1)
c2$=MID$(t$, pos2, 1)
t$=LEFT$(t$, pos1-1)+c2$+MID$(t$, pos1+1, pos2-pos1-1)+c1$+MID$(t$, pos2+1)
FN.END
FN.DEF SortDesc_TagAlong(main$, sub$)
IF LEN(main$)<>LEN(sub$) THEN FN.RTN 0
FOR i=1 TO LEN(main$)
FOR j=i+1 TO LEN(main$)
IF ASCII(main$, i)<ASCII(main$, j)
StrSwap(&main$, i, j)
StrSwap(&sub$, i, j)
ENDIF
NEXT
NEXT
FN.END
FN.DEF SetScreen(orient$,w,h)
o=(LEFT$(orient$,1)<>"v") % variable by sensor
o+=(LEFT$(orient$,1)="p") % portrait
GR.OPEN 255,0,0,0, ~
1, o-1 % show status bar, orientation
GR.SCREEN rw, rh % real width, height
GR.STATUSBAR sbh % status bar height
tw=w: BUNDLE.PUT 1, "tw", tw % target width
th=h+sbh: BUNDLE.PUT 1, "th", th % target height (previous: h/tw*rw)
y0=0: BUNDLE.PUT 1, "y0", y0 % Y-offset (previous: sbh ; before that: (th-h+sbh)/2)
sw=rw/tw: BUNDLE.PUT 1, "sw", sw % scale for width
sh=rh/th: BUNDLE.PUT 1, "sh", sh % scale for height
GR.SCALE sw, sh
FN.END
FN.DEF SetColor(c$)
GR.COLOR HEX(LEFT$(c$,2)), ~
HEX(MID$(c$,3,2)), ~
HEX(MID$(c$,5,2)), ~
HEX(RIGHT$(c$,2)), 1
FN.END
FN.DEF SetHollow(c$)
GR.COLOR HEX(LEFT$(c$,2)), ~
HEX(MID$(c$,3,2)), ~
HEX(MID$(c$,5,2)), ~
HEX(RIGHT$(c$,2)), 0
FN.END
FN.DEF Render()
IF BACKGROUND() THEN EXIT ELSE GR.RENDER
FN.END
FN.DEF AddToList(list, n, a$)
FOR i=1 TO n: LIST.ADD list, a$: NEXT
FN.END
FN.DEF gPrint(x,y,size,t$,bg$,fnt)
GR.TEXT.SETFONT fnt
GR.TEXT.SIZE size
GR.SET.STROKE size/15
GR.TEXT.DRAW plain, x, y, t$
SetHollow(bg$)
GR.TEXT.DRAW border, x, y, t$
FN.RTN plain
FN.END
FN.DEF Label$(key$)
BUNDLE.GET 1, LOWER$(key$), e$
FN.RTN e$
FN.END
FN.DEF ScrabbleVal(l$) % scrabble value for a letter
BUNDLE.GET 1, "val("+l$+")", v
FN.RTN v
FN.END
FN.DEF ColorVal(c$) % value for a colored tile
FN.RTN MAX(0, VAL(c$)-1) % normal/fire=0 ; green=1 ; gold=2 ; saphire=3
FN.END
FN.DEF Score(w$, c$, lvl, b$) % score of a word w$: depends on word, its letters colors, level, and bonus word
bgd=0 % background for score bubble: 0_normal_white/1_green/2_gold/3_saphire/4_multiple_colors/5_bonus
mf=50+10*SQR(lvl-1) % multiplying factor (depends on level)
FOR i=1 TO LEN(w$) % calculate score for each letter
lv = ScrabbleVal(MID$(w$, i, 1)) % lv = letter value
% count colored letters for final score multiplier
cv = ColorVal(MID$(c$, i, 1)) % cv = color value
green+=(cv=1): gold+=(cv=2): saphire+=(cv=3)
% Update intermediate score with score for this letter
score+=mf*lv
NEXT
% Add word-length bonus to final score
score+=mf*(LEN(w$)-3)*(LEN(w$)-2)/2
% Apply color multiplier to final score
score*=MIN(6, 1.5^green * 2^gold * 2.5^saphire)
IF green THEN bgd=1
IF gold THEN bgd=2
IF saphire THEN bgd=3
IF green+gold+saphire>1 THEN bgd=4
% Apply bonus if word is bonus-word
IF w$=b$ THEN score*=4
IF w$=b$ THEN bgd=5
BUNDLE.PUT 1, "bgd", bgd
FN.RTN 10*CEIL(score/10)
FN.END
RETURN % End of Functions
%==========================================================
Initialization:
BUNDLE.CREATE global % bundle index = #1
SetScreen("portrait", 640, 960)
BUNDLE.GET global, "y0", y0
BUNDLE.GET global, "sw", sw
BUNDLE.GET global, "sh", sh
% Load game fonts
FONT.LOAD fnt1, "Kraash Black.ttf"
FONT.LOAD fnt2, "lockergnome.ttf"
FONT.LOAD fnt3, "cooper-black.ttf"
FONT.LOAD fnt4, "berylium rg.ttf"
% List languages available for menus (labels) & for game (dictionaries)
LoadFlag("lng")
SPLIT lng$[], lng$
ARRAY.LENGTH nlng, lng$[]
FOR i=1 TO nlng
LoadFlag(lng$[i])
NEXT
% Fill some arrays
ARRAY.LOAD progress[], 91, 114, 134, 152, 170, 188, 215, 229, 250, 269, 286, ~
312, 336, 352, 370, 390, 407, 429, 444, 468, 495, 510, 530, 549, 566
ARRAY.LOAD bookpile[], 38, 44, 36, 38, 35, 30, ~
29, 29, 46, 13, 32, 20, 38, 31, 31, 24, 26
ARRAY.LOAD vibr[], 0, 500
%==========================================================
% Create menu for resource downloader
DLinit:
GR.BITMAP.LOAD bmptsc, "titlescreen.png"
GR.BITMAP.LOAD bmptwm, "titleworm.png"
GR.BITMAP.LOAD bmpttl, "title.png"
GR.BITMAP.LOAD bmpbpl, "bookpile.png"
IF !allresok % Missing game resources: download them
DLscreen:
MKDIR "fr_sounds"
MKDIR "en_sounds"
GR.CLS
GR.BITMAP.DRAW nul, bmptsc, 0, y0 % tsc = title screen
GR.BITMAP.DRAW nul, bmptwm, -199, y0+529 % twm = title worm
FOR x=-160 TO 40 STEP 20: GR.MODIFY nul, "x", x: Render(): NEXT
GR.MODIFY nul, "x", 0: Render()
PAUSE 400
GR.BITMAP.DRAW nul, bmpttl, 7, 999 % ttl = bookworm title
FOR y=967 TO -33 STEP -40: GR.MODIFY nul, "y", y0+y: Render(): NEXT
GR.MODIFY nul, "y", y0+7: Render()
GR.BITMAP.SIZE bmpbpl, w, h % bpl = bookpile
GR.BITMAP.CREATE bmplng, w, h
GR.BITMAP.DRAW nul, bmplng, 220, y0+270
GR.TEXT.ALIGN 2 % centered
SetColor("ffffff77"): txop1=gPrint(320,y0+880,35,"DOWNLOADING","ffb79433",fnt3)
SetColor("ffffff77"): txop2=gPrint(320,y0+920,33,"GAME RESOURCES...","ffb79433",fnt3)
SetColor("00000000"): GR.RECT fade,0,y0,640,y0+960: GR.HIDE fade
SetColor("ffffff77")
pct=0
ARRAY.LENGTH al, resource$[]
FOR i=1 TO al % Download all resources from internet
% Show progress by stacking on bookpile
IF INT(17*i/al)>pct
yt+=bookpile[++pct]
IF bmptmp THEN GR.BITMAP.DELETE bmptmp
GR.BITMAP.CROP bmptmp, bmpbpl, 0, h-yt, w, yt
GR.BITMAP.DRAWINTO.START bmplng
GR.BITMAP.DRAW nul, bmptmp, 0, h-yt
GR.BITMAP.DRAWINTO.END
Render()
ENDIF
% For each resource download, make the bottom label blink
FILE.EXISTS fe, resource$[i]
IF !fe
DL(resource$[i])
GR.HIDE txop1: GR.HIDE txop1+1
GR.HIDE txop2: GR.HIDE txop2+1
Render(): PAUSE 15
GR.SHOW txop1: GR.SHOW txop1+1
GR.SHOW txop2: GR.SHOW txop2+1
Render()
ENDIF
NEXT
% All done :)
GR.MODIFY txop1, "text", "DOWNLOAD COMPLETE!"
GR.MODIFY txop1+1, "text", "DOWNLOAD COMPLETE!"
GR.MODIFY txop2, "text", ""
GR.MODIFY txop2+1, "text", ""
Render(): PAUSE 1500
GOSUB FadeOut
GR.BITMAP.DELETE bmptmp: bmptmp=0
GR.BITMAP.DELETE bmplng: bmplng=0
GR.CLS
ENDIF
% Load further resources
LoadMainResources:
GR.BITMAP.LOAD bmpopb, "openbook.png"
GR.BITMAP.LOAD bmpbtn, "button.png"
bmpsnd=LoadPngSeries("snd")
SOUNDPOOL.OPEN 20
IF gLng$="en" | gLng$="no" THEN sLng$="en" ELSE sLng$="fr" % sLng = sound language
FOR i=1 TO 23
SOUNDPOOL.LOAD nul, INT$(i)+".mp3"
IF nul<=0 THEN SOUNDPOOL.LOAD nul, INT$(i)+".wav"
IF nul<=0 THEN SOUNDPOOL.LOAD nul, sLng$+"_sounds/"+INT$(i)+".mp3"
IF nul<=0 THEN Fatal("Fatal error:\nSound #" + INT$(i) + " (mp3/wav) not found!")
IF i=1 THEN snd=nul-1
NEXT
AUDIO.LOAD sfx, "1.wav"
% At first start: choose game language
IF gLng$="" THEN GOSUB ChangeLanguage
%==========================================================
MainMenu:
GOSUB LoadLabels
DIM scrabble$[1]: DIM spare$[1]
GOSUB LoadScrabble
GR.CLS: ptrbk1=0: ptrbk2=0: ptrbk3=0: ptrdlg=0
GR.BITMAP.DRAW nul, bmptsc, 0, y0 % tsc = title screen
GR.TEXT.ALIGN 2 % centered
SetColor("ffffff77"): txop1=gPrint(320,y0+880,32,"~Open Source~","ffb79433",fnt3)
GR.TEXT.UNDERLINE 1
SetColor("ffffff77"): txop2=gPrint(320,y0+915,32,"mougino.free.fr","ffb79433",fnt3)
GR.TEXT.UNDERLINE 0
GR.BITMAP.DRAW ptrsnd, bmpsnd+1-mute, 5, y0+856 % mute/unmute symbol
IF !bmptfl THEN GR.BITMAP.SCALE bmptfl, BmpFlag(gLng$), 82, 53 % tfl = tiny flag
GR.BITMAP.DRAW ptrglg, bmptfl, 558, y0+845 % glg = game language
IF !bmpcfl THEN GR.BITMAP.SCALE bmpcfl, BmpFlag("lng"), 75, 48 % cfl = change flag
GR.BITMAP.DRAW ptrclg, bmpcfl, 565, y0+902 % clg = change language
GR.GROUP settings, txop1, txop1+1, txop2, txop2+1, ptrsnd, ptrglg, ptrclg
GR.HIDE settings
GR.BITMAP.DRAW nul, bmptwm, 0, y0+529 % twm = title worm
IF !dejavu
FOR x=-160 TO 40 STEP 20: GR.MODIFY nul, "x", x: Render(): NEXT
GR.MODIFY nul, "x", 0: Render()
PAUSE 200
IF !mute THEN SOUNDPOOL.PLAY sid, snd+9
PAUSE 200
ENDIF
GOSUB MakeHowtoButton
GR.BITMAP.DRAW ptrbk3, bmpbk3, 139, y0+682
IF !dejavu
FOR y=-158 TO 682 STEP 40: GR.MODIFY ptrbk3, "y", y0+y: Render(): NEXT
ENDIF
GOSUB MakeNewGameButton
GR.BITMAP.DRAW ptrbk2, bmpbk2, 128, y0+494
IF !dejavu
FOR y=-186 TO 494 STEP 40: GR.MODIFY ptrbk2, "y", y0+y: Render(): NEXT
ENDIF
GOSUB MakeContinueButton % contains declaration of 'savefile'
GR.BITMAP.DRAW ptrbk1, bmpbk1, 84, y0+305
IF !dejavu
FOR y=-175 TO 305 STEP 40: GR.MODIFY ptrbk1, "y", y0+y: Render(): NEXT
ENDIF
GR.BITMAP.DRAW nul, bmpttl, 7, y0+7 % ttl = bookworm title
IF !dejavu
FOR y=967 TO -33 STEP -40: GR.MODIFY nul, "y", y0+y: Render(): NEXT
GR.MODIFY nul, "y", y0+7: Render()
ENDIF
IF debug % Add diagonal "debug" on title
SetColor("ffff0000")
GR.ROTATE.START -45,320,y0+200
gPrint(320,y0+200,100,"~debug~","ffffffff",fnt3)
GR.ROTATE.END
ENDIF
SetColor("00000000"): GR.RECT fade,0,y0,640,y0+960: GR.HIDE fade
SetColor("ff000000"): GR.SHOW settings
IF dejavu THEN GOSUB FadeIn ELSE Render()
dejavu=1
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MainMenuInput:
delay=-1: detectshake=0 % infinite (blocking) WaitInput and WaitRelease
GOSUB WaitInput
IF backkey | inbgnd
IF isAPK THEN EXIT ELSE END "Closed."
ENDIF
IF touched
% Tap on 'Continue'
IF savefile & x>84 & y>305 & x<84+556 & y<305+189
IF !mute THEN SOUNDPOOL.PLAY sid, snd+23,0.99,0.99
GOTO GameStart
% Tap on 'How to play'
ELSEIF x>139 & y>682 & x<139+501 & y<682+92
IF !mute THEN SOUNDPOOL.PLAY sid, snd+23,0.99,0.99
GOTO HowTo
% Tap on 'New game'
ELSEIF x>128 & y>494 & x<128+512 & y<494+190
startnew=1
IF savefile
Dlg1:
tit$=Label$("dlg1title")
msg$=Label$("dlg1msg")
btn1$=Label$("dlg1btn1")
btn2$=Label$("dlg1btn2")
GOSUB DialogMessage
IF debug THEN RETURN
IF inbgnd THEN EXIT
startnew=btn2
IF startnew THEN FILE.DELETE nul, "bookworm.sav": GOSUB MakeContinueButton
ENDIF
IF startnew
IF !mute THEN SOUNDPOOL.PLAY sid, snd+23,0.99,0.99
GOTO GameStart
ENDIF
% Type in the footer
ELSEIF y>812
IF x<95 % Mute button
GOSUB ToggleMute
ELSEIF x>558 % Flags
GOSUB FadeOut
GOSUB ChangeLanguage
GOTO MainMenu
ELSE % Middle of footer
BROWSE "http://mougino.free.fr/code/index.php?p=Bookworm"
IF isAPK THEN EXIT ELSE END "Done."
ENDIF
ENDIF
ENDIF
GOTO MainMenuInput
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MakeHowtoButton:
GR.BITMAP.LOAD tmp, "book3.png"
IF bmpbk3 THEN GR.BITMAP.DELETE bmpbk3
GR.BITMAP.CREATE bmpbk3, 501, 92
GR.BITMAP.DRAWINTO.START bmpbk3
GR.BITMAP.DRAW nul, tmp, 0, 0
SetColor("ffff00ff"): gPrint(501/2,(92+30)/2,30,Label$("howto"),"ff550055",fnt1)
GR.BITMAP.DRAWINTO.END
IF ptrbk3 THEN GR.MODIFY ptrbk3, "bitmap", bmpbk3
GR.BITMAP.DELETE tmp
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MakeNewGameButton:
GR.BITMAP.LOAD tmp, "book2.png"
IF bmpbk2 THEN GR.BITMAP.DELETE bmpbk2
GR.BITMAP.CREATE bmpbk2, 512, 190
GR.BITMAP.DRAWINTO.START bmpbk2
GR.BITMAP.DRAW nul, tmp, 0, 0
SetColor("ffffff00"): gPrint(512/2,(190+40)/2,40,Label$("newgame"),"ffb79433",fnt1)
GR.BITMAP.DRAWINTO.END
IF ptrbk2 THEN GR.MODIFY ptrbk2, "bitmap", bmpbk2
GR.BITMAP.DELETE tmp
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MakeContinueButton:
FILE.EXISTS savefile, "bookworm.sav"
GR.BITMAP.LOAD tmp, "book1.png"
IF bmpbk1 THEN GR.BITMAP.DELETE bmpbk1
GR.BITMAP.CREATE bmpbk1, 556, 189
GR.BITMAP.DRAWINTO.START bmpbk1
GR.BITMAP.DRAW nul, tmp, 0, 0
IF savefile
SetColor("ff00ff00"): c$="ff005500"
ELSE
SetColor("ff7a9729"): c$="ff5b721c"
ENDIF
gPrint(556/2,(189+50)/2,50,Label$("continue"),c$,fnt1)
GR.BITMAP.DRAWINTO.END
IF ptrbk1 THEN GR.MODIFY ptrbk1, "bitmap", bmpbk1
GR.BITMAP.DELETE tmp
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FadeOut:
GR.SHOW fade: FOR i=5 TO 255 STEP 25: GR.MODIFY fade,"alpha",i: Render(): PAUSE 15: NEXT
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FadeIn:
GR.SHOW fade: FOR i=250 TO 0 STEP -25: GR.MODIFY fade,"alpha",i: Render(): PAUSE 15: NEXT: GR.HIDE fade: Render()
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ToggleMute:
GOSUB FadeOut
mute=1-mute: GR.MODIFY ptrsnd, "bitmap", bmpsnd+1-mute
GOSUB FadeIn
GOSUB SaveConfig: GOSUB WaitRelease
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ChangeLanguage:
GR.CLS
GR.BITMAP.DRAW nul, bmptsc, 0, y0 % tsc = title screen
GR.BITMAP.DRAW nul, bmptwm, 0, y0+529 % twm = title worm
GR.TEXT.ALIGN 1 % left
IF gLng$<>"" THEN SetColor("ffb2ed21"): gPrint(10,y0+30,40,"<<< ","ff8ebc1a",fnt3)
FOR i=1 TO nlng
FILE.EXISTS fe, "labels_"+lng$[i]+".txt"
IF !fe THEN DL("labels_"+lng$[i]+".txt")
LoadLngN(lng$[i])
GR.BITMAP.DRAW nul, BmpFlag(lng$[i]), 140, y0+36+808*(i-1)/nlng
IF i=1 THEN ptrlng=nul
SetColor("ffffff77"): gPrint(265,y0+85+808*(i-1)/nlng,50,LngN$(lng$[i]),"ffb79433",fnt3)
NEXT
SetColor("00000000"): GR.RECT fade,0,y0,640,y0+960: GR.HIDE fade
SetColor("ffffff77")
GOSUB FadeIn
LangInput:
GOSUB WaitInput
IF inbgnd THEN EXIT
IF backkey | (gLng$<>"" & touched & x<100 & y<80) % Back
GOSUB FadeOut
IF gLng$="" THEN EXIT ELSE RETURN
ENDIF
IF touched & x>124 & y<808 % Touch in language zone
slng=CEIL(y*nlng/808) % slng = selected language
chln=(lng$[slng]<>gLng$) % chln = changed language
IF debug THEN chln=1 % force new language in debug mode
% Handle language changed
IF chln
FILE.EXISTS savefile, "bookworm.sav"
IF savefile
tit$=Label$("dlg1title")
msg$=Label$("dlg1msg")
btn1$=Label$("dlg1btn1")
btn2$=Label$("dlg1btn2")
GOSUB DialogMessage
IF inbgnd THEN EXIT
chln=btn2
IF chln THEN FILE.DELETE nul, "bookworm.sav" ELSE GOSUB WaitRelease: GOTO LangInput
ENDIF
gLng$=lng$[slng]
mLng$=lng$[slng]
GOSUB NewLangAnim
IF debug % force download freshest labels
FILE.DELETE fd, "labels_"+gLng$+".txt"
POPUP "Force downloading 'labels_"+gLng$+".txt'"
ENDIF
CheckAndDL("labels_"+gLng$+".txt")
CheckAndDL("letters_"+gLng$+".txt")
CheckAndDL("3_letter_words_"+gLng$+".txt")
CheckAndDL("4_letter_words_"+gLng$+".txt")
CheckAndDL("dict_"+gLng$+".txt")
dico$="" % reset dictionary > will be loaded when starting new game
IF bmptfl THEN GR.BITMAP.DELETE bmptfl: bmptfl=0 % tfl = tiny flag > reset it!
GOSUB SaveConfig
dejavu=0
% User selected same language > show animation anyway
ELSE
GOSUB NewLangAnim
ENDIF
GOSUB FadeOut
% Clean up animation bitmaps
IF bmptmp THEN GR.BITMAP.DELETE bmptmp: bmptmp=0
IF bmplng THEN GR.BITMAP.DELETE bmplng: bmplng=0
ELSE % Touch anywhere else
GOSUB WaitRelease
GOTO LangInput
ENDIF
GOSUB WaitRelease
RETURN
%==========================================================
NewLangAnim:
GR.HIDE ptrlng+3*(slng-1)
GR.BITMAP.CREATE bmplng, 112*10, 72*10
GR.BITMAP.DRAW ptrani, bmplng, 140, y0+36+808*(slng-1)/nlng
FOR i=1.5 TO 10 STEP 0.5
IF bmptmp THEN GR.BITMAP.DELETE bmptmp
GR.BITMAP.SCALE bmptmp, BmpFlag(gLng$), 112*i, 72*i
GR.BITMAP.DRAWINTO.START bmplng
GR.BITMAP.DRAW nul, bmptmp, 0, 0
GR.BITMAP.DRAWINTO.END
GR.MODIFY ptrani, "alpha", 255-25*i
GR.MODIFY ptrani, "x", 140-112*i*0.8
GR.MODIFY ptrani, "y", y0+36+808*(slng-1)/nlng-72*i*0.8
Render(): PAUSE 20
NEXT
RETURN
%==========================================================
HowTo:
IF !bmpbbl
GR.BITMAP.LOAD bmpbbl, "howtobubble.png"
bmpnx=LoadPngSeries("next")
GR.BITMAP.SCALE bmppv, bmpnx, -140, 140
GR.BITMAP.SCALE nul, bmpnx+1, -140, 140
bmphow=LoadPngSeries("howto")
ENDIF
IF debug % Show all DialogMessages first in debug mode
FOR dl=1 TO 8
GOSUB dl, Dlg1, Dlg2, Dlg3, Dlg4, Dlg5, Dlg6, Dlg7, Dlg8
IF inbgnd THEN END "Done."
NEXT
ENDIF
GR.CLS
% howto background, worm, and bubble
GR.BITMAP.DRAW nul, bmptsc, 0, y0
GR.BITMAP.DRAW nul, bmptwm, -199, y0+529
FOR x=-160 TO 40 STEP 20: GR.MODIFY nul, "x", x: Render(): NEXT
GR.MODIFY nul, "x", 0: Render()
GR.BITMAP.DRAW nul, bmpbbl, 134, y0+527
howtoscr=0
% howto image, next/prev buttons
GR.BITMAP.DRAW ptrhow, bmphow+howtoscr, 663, y0+37
FOR i=1 TO 16
GR.MODIFY nul, "alpha", 16*i-1 % bubble
GR.MODIFY ptrhow, "x", 663-i*40: Render()
NEXT
GR.BITMAP.DRAW ptrnxt, bmpnx+1, 480, y0+819
GR.BITMAP.DRAW ptrprv, bmppv, 17, y0+819
GR.HIDE ptrprv
% howto tip text
SetColor("ff000000"): GR.TEXT.SETFONT fnt4: GR.TEXT.SIZE 36
GR.TEXT.ALIGN 1 % left
GR.TEXT.DRAW txtip, 190, y0+600, ""
GR.TEXT.DRAW nul, 190, y0+658, ""
GR.TEXT.DRAW nul, 190, y0+714, ""
GR.TEXT.DRAW nul, 190, y0+772, ""
% back button and howto screen number (n/7)
SetColor("ffb2ed21"): gPrint(10,y0+30,40,"< " + Label$("back"),"ff8ebc1a",fnt3)
GR.TEXT.ALIGN 2 % centered
SetColor("ffb2ed21"): howtext = gPrint(320,y0+920,75,INT$(1+howtoscr)+"/7","ff8ebc1a",fnt3)
GOSUB HowtoFillTip
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HowToInput:
delay=300: detectshake=0 % 300 ms delay for WaitInput and WaitRelease
DO
GR.MODIFY ptrprv, "bitmap", bmppv+1
GR.MODIFY ptrnxt, "bitmap", bmpnx
Render()
GOSUB WaitInput
IF touched | backkey | inbgnd THEN D_U.BREAK
GR.MODIFY ptrprv, "bitmap", bmppv
GR.MODIFY ptrnxt, "bitmap", bmpnx+1
Render()
GOSUB WaitInput
UNTIL touched | backkey | inbgnd
IF inbgnd THEN EXIT
IF backkey THEN GOTO MainMenu
IF touched & x<320 & y<100 THEN
IF !mute THEN SOUNDPOOL.PLAY sid, snd+23,0.99,0.99
GOTO MainMenu
ENDIF
DO
GR.MODIFY ptrprv, "bitmap", bmppv+1
GR.MODIFY ptrnxt, "bitmap", bmpnx
Render()
GOSUB WaitRelease
IF !touched | backkey | inbgnd THEN D_U.BREAK
GR.MODIFY ptrprv, "bitmap", bmppv
GR.MODIFY ptrnxt, "bitmap", bmpnx+1
Render()
GOSUB WaitRelease
UNTIL !touched | backkey | inbgnd
IF inbgnd THEN EXIT
IF backkey THEN GOTO MainMenu
IF x>=320 & y>810 & howtoscr<6 % Next how-to
IF !mute THEN SOUNDPOOL.PLAY sid, snd+23,0.99,0.99
FOR x=23 TO -577 STEP -60: GR.MODIFY ptrhow, "x", x: Render(): NEXT
howtoscr++
GR.MODIFY ptrhow, "bitmap", bmphow+howtoscr
FOR x=623 TO 23 STEP -60: GR.MODIFY ptrhow, "x", x: Render(): NEXT
GR.MODIFY howtext, "text", INT$(1+howtoscr)+"/7"
GR.MODIFY howtext+1, "text", INT$(1+howtoscr)+"/7"
IF howtoscr=1 THEN GR.SHOW ptrprv
IF howtoscr=6 THEN GR.HIDE ptrnxt
GOSUB HowtoFillTip
ELSEIF x<320 & y>810 & howtoscr>0 % Previous how-to
IF !mute THEN SOUNDPOOL.PLAY sid, snd+23,0.99,0.99
FOR x=23 TO 623 STEP 60: GR.MODIFY ptrhow, "x", x: Render(): NEXT
howtoscr--
GR.MODIFY ptrhow, "bitmap", bmphow+howtoscr
FOR x=-577 TO 23 STEP 60: GR.MODIFY ptrhow, "x", x: Render(): NEXT
GR.MODIFY howtext, "text", INT$(1+howtoscr)+"/7"
GR.MODIFY howtext+1, "text", INT$(1+howtoscr)+"/7"
IF howtoscr=0 THEN GR.HIDE ptrprv
IF howtoscr=5 THEN GR.SHOW ptrnxt
GOSUB HowtoFillTip
ENDIF
GOTO HowToInput
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HowtoFillTip:
FOR i=0 TO 3: GR.MODIFY txtip+i , "text", "": NEXT
SPLIT msg$[], Label$("tip"+INT$(howtoscr+1)), "\n"
ARRAY.LENGTH al, msg$[]
FOR i=1 TO al: GR.MODIFY txtip+i-1 , "text", msg$[i]: NEXT
ARRAY.DELETE msg$[]
Render()
IF !mute
IF howtoscr=0
SOUNDPOOL.PLAY sid, snd+1: PAUSE 300
FOR i=1 TO 3: SOUNDPOOL.PLAY sid, snd+19,0.99,0.99: PAUSE 100: NEXT
ELSEIF howtoscr=1
SOUNDPOOL.PLAY sid, snd+14
ELSEIF howtoscr=2
SOUNDPOOL.PLAY sid, snd+10
ELSEIF howtoscr=3
SOUNDPOOL.PLAY sid, snd+11
ELSEIF howtoscr=4
SOUNDPOOL.PLAY sid, snd+6,0.99,0.99
ELSEIF howtoscr=5
SOUNDPOOL.PLAY sid, snd+2,0.99,0.99
ELSEIF howtoscr=6
SOUNDPOOL.PLAY sid, snd+6,0.99,0.99
ENDIF
ENDIF
RETURN
%==========================================================
GameStart:
debug=0 % disable debug mode when playing
% Load resources at first run
IF !bmpbrd
GR.BITMAP.LOAD bmpbrd, "board.png"
GR.BITMAP.LOAD bmpflm, "flames.png"
bmpwrm=LoadPngSeries("worm")
bmptil=LoadPngSeries("tile")
bmpbul=LoadPngSeries("bubble")
GR.BITMAP.SCALE bmptiny, bmptil, 60, 60
FOR i=1 TO 6: GR.BITMAP.SCALE nul, bmptil+i, 60, 60: NEXT
DIM tiltyp[7,7]
DIM tapped[7,7]
DIM bonusword$[1]
anim=10 % animation steps
ENDIF
% Load savefile / or start from zero
IF shaken
ARRAY.SHUFFLE scrabble$[]: ARRAY.COPY scrabble$[50], spare$[]
ELSE % continue / new game
SENSORS.OPEN 1 % acceleration and orientation sensor
FILE.EXISTS savefile, "bookworm.sav"
IF savefile % continue
GOSUB LoadGame
ELSE % new game
ARRAY.SHUFFLE scrabble$[]: ARRAY.COPY scrabble$[50], spare$[]
score=0: lvl=1
ARRAY.DELETE tiltyp[]: DIM tiltyp[7,7]
bonusletters=3
bonusidx=0 % no bonus word (yet) at level 1
ENDIF
GOSUB LoadBonusWords
ENDIF
pvlvl=1000*(lvl^2-1) % opening score for this level
nxlvl=1000*((lvl+1)^2-1) % score to obtain to reach next level
progress=1+MIN(24, INT(24*(score-pvlvl)/(nxlvl-pvlvl)))
% fade-out title screen (or previous game screen if shaken)
GOSUB FadeOut
IF !LEN(dico$)
CheckExist("dict_"+gLng$+".txt")
GRABFILE dico$, "dict_"+gLng$+".txt"
ENDIF
% prepare game screen
GR.CLS: ptrhot=0: ptrsel=0: ptrdlg=0
SetColor("ff000000")
GR.BITMAP.DRAW nul, bmpbrd, 0, y0
GR.BITMAP.DRAW ptrwrm, bmpwrm, 3, y0
% bubble
GR.BITMAP.DRAW ptrbul, bmpbul, 128, y0+10: GR.HIDE ptrbul
SetColor("ffffdd72"): txmot = gPrint(312,y0+43,30,"DAFT","ff000000",fnt2)
SetColor("fffca726"): txworth = gPrint(312,y0+102,60,"+520","ff000000",fnt3)
SetColor("ff006104"): GR.TEXT.SIZE 20: GR.TEXT.SETFONT fnt4: GR.TEXT.BOLD 1
GR.TEXT.DRAW txsubmit, 312, y0+145, Label$("submit")
GR.GROUP txgo, txmot, txmot+1, txworth, txworth+1, txsubmit
SetColor("ff000000"): GR.TEXT.SETFONT fnt4: GR.TEXT.SIZE 36
SPLIT msg$[], Label$("hint1"), "\n"
ARRAY.LENGTH al, msg$[]: IF al<>3 THEN Fatal("Malformed label: hint1 - must be 3 lines")
GR.TEXT.DRAW txhint, 312, y0+58, msg$[1]
GR.TEXT.DRAW nul, 312, y0+98, msg$[2]
GR.TEXT.DRAW nul, 312, y0+138, msg$[3]
ARRAY.DELETE msg$[]
GR.GROUP txnogo, txhint, txhint+1, txhint+2
% bonus word
SetColor("ffe4cb33"): GR.TEXT.SIZE 25: GR.TEXT.SETFONT fnt3: GR.TEXT.BOLD 0
e$=Label$("bonus"): i=IS_IN(" ", e$)
GR.TEXT.DRAW nul, 552, y0+43, LEFT$(e$, i-1)
GR.TEXT.DRAW nul, 552, y0+65, MID$(e$, i+1)
IF bonusidx THEN bonus$=bonusword$[bonusidx]
SetColor("fff8ff01"): txbonus = gPrint(554,y0+120,30,bonus$,"ff000000",fnt2)
IF !bonusreminder THEN bonusreminder=5 % reminder for bonus word after 5 submits
% bottom bar: score, level
SetColor("ff000000"): GR.RECT ptrprogress, progress[progress], y0+862, 567, y0+957
SetColor("ffffc641"): txscore = gPrint(320,y0+930,60,INT$(score),"ff000000",fnt2)
SetColor("ffb4f200"): GR.TEXT.SIZE 14: GR.TEXT.SETFONT "Normal": GR.TEXT.BOLD 1
GR.TEXT.DRAW nul, 606, y0+900, Label$("level")
SetColor("ffb4f200"): GR.TEXT.SIZE 20
GR.TEXT.DRAW txlvl, 606, y0+926, INT$(lvl): GR.TEXT.BOLD 0
% hot layer and selection layer
IF !bmphot THEN GR.BITMAP.CREATE bmphot, 7*90, 7*91+40
GOSUB ResetHot
IF !bmpsel THEN GR.BITMAP.CREATE bmpsel, 7*90, 7*91+40
GOSUB ResetSel
% fade-in game screen
SetColor("ff000000"): GR.RECT fade,0,y0,640,y0+960
GOSUB FadeIn
IF !shaken & !mute THEN SOUNDPOOL.PLAY sid, snd+13
% cascade tiles
danger=0
FOR i=0 to 48
y=1+MOD(i,7): x=1+FLOOR(i/7)
GR.BITMAP.DRAW nul, bmptil+tiltyp[x,y], 4+(x-1)*90, y0+173+(7-y)*91+40*MOD(x-1,2)
GR.HIDE nul: IF i=0 THEN ptrtil=nul % pointer to first tile (bottom left)
IF y=1 & tiltyp[x,y]=1 THEN danger=1 % fire tile at bottom of board
NEXT
GR.TEXT.SETFONT "Normal": GR.TEXT.SIZE 50
FOR i=0 to 48
IF !MOD(i,2) & !mute THEN SOUNDPOOL.PLAY sid, snd+8,0.99,0.99
GR.SHOW ptrtil+i
y=1+MOD(i,7): x=1+FLOOR(i/7)
e$=scrabble$[i+1]: IF e$="Q" THEN e$="Qu"
GR.TEXT.DRAW nul, 49+(x-1)*90, y0+237+(7-y)*91+40*MOD(x-1,2), e$
IF i=0 THEN txletr=nul % pointer to first letter (bottom left)
Render()
NEXT
GR.BITMAP.DRAW ptrtiny, bmptiny, 0, y0: GR.HIDE ptrtiny
GR.BITMAP.DRAW ptrhot, bmphot, 4, y0+173
GR.MODIFY ptrhot, "alpha", 150
GR.BITMAP.DRAW ptrsel, bmpsel, 4, y0+173
GR.MODIFY ptrsel, "alpha", 150
Render()
% After shuffle, make fire tiles fall by 1 row + create 2 new fire tiles at the top
IF shaken
GOSUB ConsumeHotTiles: Render()
IF !gameover
PAUSE 400
x=0: y=7: GOSUB FindFreeTile % find free tile at the top row
GOSUB CreateFireTile: Render()
x=0: y=7: GOSUB FindFreeTile % find free tile at the top row
GOSUB CreateFireTile: Render()
ENDIF
ENDIF
SetColor("ff000000"): GR.RECT fade,0,y0,640,y0+960: GR.HIDE fade
SetColor("ff0000ff"): GR.SET.STROKE 10 % for word-lines
SENSORS.READ 1, s20, s21, s22
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GameInput:
IF gameover
gameover=0
GR.HIDE txgo: GR.HIDE txnogo
GR.MODIFY txworth, "text", Label$("fire"): GR.MODIFY txworth+1, "text", Label$("fire")
GR.SHOW txworth: GR.SHOW txworth+1
GR.BITMAP.DRAW ptrflm, bmpflm, 0, y0+1122
IF !mute THEN SOUNDPOOL.PLAY sid, snd+5
FOR y=1122 TO -162 STEP -10
GR.MODIFY ptrflm, "y", y0+y: Render()
NEXT
GR.MODIFY ptrwrm, "bitmap", bmpwrm+3
IF bmpsel THEN GR.BITMAP.DELETE bmpsel
GR.BITMAP.CREATE bmpsel, 7*90, 7*91+40
GR.BITMAP.DRAWINTO.START bmpsel
SetColor("ff555555")
GR.RECT nul, 0, 0, 7*90, 7*91+40
GR.BITMAP.DRAWINTO.END
GR.MODIFY ptrsel, "bitmap", bmpsel
GR.SHOW ptrsel
PAUSE 500
FOR i=250 TO 0 STEP -10: GR.MODIFY ptrflm,"alpha",i: Render(): NEXT
PAUSE 1500
FILE.DELETE nul, "bookworm.sav": savefile=0
SENSORS.CLOSE
IF !mute THEN SOUNDPOOL.PLAY sid, snd+16
Dlg2:
tit$=Label$("dlg2title")
dsz=60 % dialog size for message
msg$="\n" + Label$("dlg2msg1") + " " + INT$(score) + "\n\n"
msg$+=Label$("dlg2msg2") + " " + INT$(lvl)
btn1$=Label$("dlg2btn1")
btn2$=Label$("dlg2btn2")
GOSUB DialogMessage
IF debug THEN RETURN
IF btn2 THEN GOTO GameStart ELSE EXIT
ENDIF
% If we warned the user of a fire tile at bottom:
% next action can bring a game over...
IF danger=2 THEN danger=1
delay=-1: detectshake=1 % infinite (blocking) WaitInput and WaitRelease
GOSUB WaitInput % + report *shaken* state of phone
IF inbgnd
GOSUB SaveGame: EXIT
ELSEIF shaken
Dlg3:
tit$=Label$("dlg3title")
msg$=Label$("dlg3msg")
btn1$=Label$("dlg3btn1")
btn2$=Label$("dlg3btn2")
GOSUB DialogMessage
IF debug THEN RETURN
IF inbgnd: GOSUB SaveGame: EXIT: ENDIF
SENSORS.READ 1, s10, s11, s12
s20=s10: s21=s11: s22=s12
shaken=btn2
IF shaken
IF !mute THEN SOUNDPOOL.PLAY sid, snd+11
FOR x=1 TO 7
FOR y=1 TO 7
IF tiltyp[x,y]>1 THEN tiltyp[x,y]=0 % remove tiles 2_green/3_gold/4_saphire
NEXT
NEXT
GOTO GameStart
ENDIF
ELSEIF backkey | (touched & x<=80 & y>=851)
SENSORS.CLOSE
GOSUB SaveGame
IF !mute THEN SOUNDPOOL.PLAY sid, snd+23,0.99,0.99
GOTO MainMenu
ELSEIF touched & y>=851 % bottom bar
IF LEN(mot$)
IF !mute THEN SOUNDPOOL.PLAY sid, snd+20
GOSUB ResetSel: Render()
ENDIF
ELSEIF touched & y<=172 % upper bar
IF x>142 & x<480
GOSUB Submit
ELSEIF x>=480 & bonusidx
Dlg4:
tit$=Label$("dlg4title")
msg$=Label$("dlg4msg")
btn1$=Label$("dlg4btn1")
btn2$=Label$("dlg4btn2")
GOSUB DialogMessage
IF debug THEN RETURN
IF inbgnd: GOSUB SaveGame: EXIT: ENDIF
IF btn2
GOSUB NextBonusWord
GOSUB ConsumeHotTiles: Render()
IF !gameover
PAUSE 400
x=0: y=7: GOSUB FindFreeTile % find free tile at the top row
GOSUB CreateFireTile: Render()
ENDIF
ENDIF
ENDIF
ELSEIF touched % in the board
x=CEIL(x/90): x=MIN(7, MAX(1, x))
y=8-CEIL((y-173-40*MOD(x-1,2))/91)
IF y>=1 & y<=7
IF !tapped[x,y]
IF !mute THEN SOUNDPOOL.PLAY sid, snd+4
% Update selection
newsel=!((x=lastx & ABS(y-lasty)=1) | (ABS(x-lastx)=1 & y-lasty>=-MOD(x,2) & y-lasty<=MOD(x+1,2)))
IF newsel THEN GOSUB ResetSel
GR.BITMAP.DRAWINTO.START bmpsel
GR.BITMAP.DRAW nul, bmptil+5, (x-1)*90, (7-y)*91+40*MOD(x-1,2)
IF !newsel
GR.LINE nul, (x-1)*90+45, (7-y)*91+40*MOD(x-1,2)+45, ~
(lastx-1)*90+45, (7-lasty)*91+40*MOD(lastx-1,2)+45
ENDIF
GR.BITMAP.DRAWINTO.END
% Register touched tile
tapped[x,y]=1
lastx=x: lasty=y
lastx$+=INT$(x): lasty$+=INT$(y)
color$+=INT$(tiltyp[x,y])
e$=scrabble$[7*(x-1)+y]
IF e$="Q" THEN
e$="QU"
lastx$+=INT$(x): lasty$+=INT$(y)
color$+=INT$(tiltyp[x,y])
ENDIF
% Update word
mot$+=e$
GR.MODIFY txmot, "text", mot$: GR.MODIFY txmot+1, "text", mot$
IF LEN(mot$)=2
SPLIT msg$[], Label$("hint2"), "\n"
ARRAY.LENGTH al, msg$[]: IF al<>3 THEN Fatal("Malformed label: hint2 - must be 3 lines")
GR.MODIFY txhint, "text", msg$[1]
GR.MODIFY txhint+1, "text", msg$[2]
GR.MODIFY txhint+2, "text", msg$[3]
ARRAY.DELETE msg$[]
ELSEIF LEN(mot$)>=3
GR.HIDE txnogo
GR.SHOW txgo
ENDIF
% Check word validity
worth=0
IF LEN(mot$)>=3 % test word validity against dico
IF IS_IN("\n"+mot$+"\n", dico$) % valid
worth=Score(mot$, color$, lvl, bonus$)
GR.MODIFY txworth, "text", "+"+INT$(worth)
GR.MODIFY txworth+1, "text", "+"+INT$(worth)
GR.SHOW txworth: GR.SHOW txworth+1
GR.MODIFY txsubmit, "text", Label$("submit")
BUNDLE.GET global, "bgd", bgd
IF bgd THEN
GR.MODIFY ptrbul, "bitmap", bmpbul+bgd-1
GR.SHOW ptrbul
ELSE
GR.HIDE ptrbul
ENDIF
ELSE % not valid
GR.HIDE ptrbul
GR.HIDE txworth: GR.HIDE txworth+1
GR.MODIFY txsubmit, "text", Label$("invalid")
ENDIF
ENDIF
Render()
ENDIF
ENDIF
ENDIF
GOTO GameInput
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ResetHot:
IF bmphot THEN GR.BITMAP.DELETE bmphot
GR.BITMAP.CREATE bmphot, 7*90, 7*91+40
IF ptrhot THEN GR.MODIFY ptrhot, "bitmap", bmphot
FOR hx=1 TO 7
FOR hy=2 TO 7
IF tiltyp[hx,hy]=1 % 1_fire
GR.BITMAP.DRAWINTO.START bmphot
GR.BITMAP.DRAW nul, bmptil+6, (hx-1)*90, (8-hy)*91+40*MOD(hx-1,2)
GR.BITMAP.DRAWINTO.END
ENDIF
NEXT
NEXT
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ResetSel:
mot$="": color$="": lastx$="": lasty$=""
lastx=99: lasty=99: worth=0
ARRAY.DELETE tapped[]: DIM tapped[7,7]
IF bmpsel THEN GR.BITMAP.DELETE bmpsel
GR.BITMAP.CREATE bmpsel, 7*90, 7*91+40
IF ptrsel THEN GR.MODIFY ptrsel, "bitmap", bmpsel
GR.HIDE ptrbul
GR.HIDE txgo
SPLIT msg$[], Label$("hint1"), "\n"
ARRAY.LENGTH al, msg$[]: IF al<>3 THEN Fatal("Malformed label: hint1 - must be 3 lines")
GR.MODIFY txhint, "text", msg$[1]
GR.MODIFY txhint+1, "text", msg$[2]
GR.MODIFY txhint+2, "text", msg$[3]
ARRAY.DELETE msg$[]
GR.SHOW txnogo
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CreateFireTile:
IF !mute
VIBRATE vibr[], -1
SOUNDPOOL.PLAY sid, snd+17,0.99,0.99
ENDIF
tiltyp[x,y]=1: GR.MODIFY ptrtil+7*(x-1)+y-1, "bitmap", bmptil+1
GOSUB ResetHot
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CreateGreenTile:
IF !mute THEN SOUNDPOOL.PLAY sid, snd+21,0.99,0.99
tiltyp[x,y]=2: GR.MODIFY ptrtil+7*(x-1)+y-1, "bitmap", bmptil+2
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CreateGoldTile:
IF !mute THEN SOUNDPOOL.PLAY sid, snd+2,0.99,0.99
tiltyp[x,y]=3: GR.MODIFY ptrtil+7*(x-1)+y-1, "bitmap", bmptil+3
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CreateSaphireTile:
IF !mute THEN SOUNDPOOL.PLAY sid, snd+6,0.99,0.99
tiltyp[x,y]=4: GR.MODIFY ptrtil+7*(x-1)+y-1, "bitmap", bmptil+4
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Submit:
IF worth % valid word
AUDIO.STOP: IF !mute THEN AUDIO.PLAY sfx
GR.MODIFY ptrwrm, "bitmap", bmpwrm+1 % show swallowing worm
GR.HIDE ptrhot: GR.HIDE ptrsel: GR.SHOW ptrtiny % hide hot+selection, show tiny tile
submit++
% Register longer/highest word for end of level
IF LEN(mot$)>LEN(longest$) THEN longest$=mot$
IF worth>highest
highest=worth
highest$=mot$
ENDIF
% Is submitted word equal to the bonus word ?
changebonus=(mot$=bonus$)
% Remove the "U" in "QU" in submitted word
q=IS_IN("Q", mot$)
WHILE q
mot$=LEFT$(mot$, q)+MID$(mot$, q+2)
lastx$=LEFT$(lastx$, q)+MID$(lastx$, q+2)
lasty$=LEFT$(lasty$, q)+MID$(lasty$, q+2)
q=IS_IN("Q", mot$, q+1)
REPEAT
% Start animation to update score
scoranim=0
TIMER.SET 40
% Swallow each letter
crunch=0: colored=0
FOR i=1 TO LEN(mot$)
x=VAL(MID$(lastx$,i,1)): y=VAL(MID$(lasty$,i,1))
GR.HIDE ptrtil+7*(x-1)+y-1 % hide tile
GR.HIDE txletr+7*(x-1)+y-1 % and letter
GR.MODIFY ptrtiny, "bitmap", bmptiny+tiltyp[x,y]
% Cancel danger when fire tile at bottom is swallowed:
IF y=1 & tiltyp[x,y]=1 & danger THEN danger=0
% Count colored tiles: 2_green/3_gold/4_saphire
IF tiltyp[x,y]>1 THEN colored++
FOR j=0 TO anim % animate swallow
IF mute THEN LET done=0 ELSE AUDIO.ISDONE done
IF done & !MOD(j,5)
SOUNDPOOL.PLAY sid, snd+19,0.99,0.99
crunch++
ENDIF
xx=68+(anim-j)*(4+(x-1)*90-68)/anim
yy=y0+68+(anim-j)*(173+(8-y)*91+40*MOD(x-1,2)-68-y0)/anim
GR.MODIFY ptrtiny, "x", xx, "y", yy
Render()
NEXT
NEXT
IF !crunch & !mute
FOR i=1 TO LEN(mot$): SOUNDPOOL.PLAY sid, snd+19,0.99,0.99: PAUSE 50: NEXT
ENDIF
GR.HIDE ptrtiny % hide tiny tile
GR.MODIFY ptrwrm, "bitmap", bmpwrm+2*(danger>0) % back to normal/danger worm
% Replace swallowed letters
SortDesc_TagAlong(&lasty$, &lastx$)
FOR i=1 TO LEN(mot$)
x=VAL(MID$(lastx$,i,1)): y=VAL(MID$(lasty$,i,1))
GR.SHOW ptrtil+7*(x-1)+y-1: GR.SHOW txletr+7*(x-1)+y-1
% make all tiles in the column fall and replace top tile with a spare
swallowed$=MID$(mot$,i,1)
GOSUB FallAndFill: Render()
NEXT
ARRAY.COPY spare$[], scrabble$[50]
% Consume all hot tiles which are under fire tiles (if any)
GOSUB ConsumeHotTiles: Render()
IF gameover THEN RETURN
% Punish short words with a fire tile
% 3-letter-long words -> probability of fire tile 1:3
IF LEN(mot$)<=3 & !FLOOR(3*RND())
PAUSE 400
x=0: y=7: GOSUB FindFreeTile % find free tile at the top row
GOSUB CreateFireTile: Render()
% 4-letter-long words -> probability of fire tile 1:4
ELSEIF LEN(mot$)=4 & !FLOOR(4*RND())
PAUSE 400
x=0: y=7: GOSUB FindFreeTile % find free tile at the top row
GOSUB CreateFireTile: Render()
% ..reward long words (5 letters or more) with a gold tile, probability 1:2
ELSEIF LEN(mot$)>=5 & !FLOOR(2*RND())
PAUSE 400
x=0: y=0: GOSUB FindFreeTile % find free tile anywhere in the board
GOSUB CreateGoldTile: Render()
ENDIF
% Reward multi-colored word with a saphire tile (systematically)
IF colored>1
PAUSE 400
x=0: y=0: GOSUB FindFreeTile % find free tile anywhere in the board
GOSUB CreateSaphireTile: Render()
ENDIF
% Randomly create green tile(s) (probability 1:5)
IF !FLOOR(5*RND())
PAUSE 400
x=0: y=7: GOSUB FindFreeTile % find free tile at the top row
GOSUB CreateGreenTile: Render()
IF !FLOOR(2*RND()) % 1 time out of 2, create a second green tile
x=0: y=7: GOSUB FindFreeTile % find free tile at the top row
GOSUB CreateGreenTile: Render()
ENDIF
ENDIF
% Finish
GR.SHOW ptrsel: GOSUB ResetSel
GR.SHOW ptrhot: GOSUB ResetHot
Render()
% Change bonus word ?
IF changebonus
submit=0 % reset reminder for bonus word
% Switch to 4-letter words after level 20 and 10 or more bonus words found:
IF lvl>=20 & bonusidx>=10 & bonusletters=3
ARRAY.LENGTH al, bonusword$[]
bonusidx=al+1
ENDIF
GOSUB NextBonusWord
ENDIF
% Activate bonus words after first "submit" of level 2
IF lvl=2 & !bonusidx
GOSUB NextBonusWord
submit=0 % reset reminder
Dlg5:
tit$=Label$("dlg5title")
msg$=Label$("dlg5msg")
btn1$=Label$("dlg5btn")
btn2$=""
GOSUB DialogMessage
IF debug THEN RETURN
IF inbgnd: GOSUB SaveGame: EXIT: ENDIF
ENDIF
% Next level ?
IF progress=25
PAUSE 200
IF !mute THEN SOUNDPOOL.PLAY sid, snd+12
Dlg6:
e$=Label$("dlg6title"): i=IS_IN(" ", e$)
tit$=LEFT$(e$, i) + INT$(lvl) + MID$(e$, i)
msg$=Label$("dlg6msg1") + "\n" + highest$ + " (" + INT$(highest) + " " + Label$("dlg6msg2") + ")\n\n"
msg$+=Label$("dlg6msg3") + "\n" + longest$ + " (" + INT$(LEN(longest$)) + " " + Label$("dlg6msg4") + ")"
btn1$=Label$("dlg6btn")
btn2$=""
GOSUB DialogMessage
IF debug THEN RETURN
highest=0: highest$="": longest$=""
lvl++
IF inbgnd: GOSUB SaveGame: EXIT: ENDIF
pvlvl=1000*(lvl^2-1) % opening score for this level
nxlvl=1000*((lvl+1)^2-1) % score to obtain to reach next level
progress=1+MIN(24, INT(24*(score-pvlvl)/(nxlvl-pvlvl)))
GR.MODIFY ptrprogress, "left", progress[progress]
GR.MODIFY txlvl, "text", INT$(lvl)
GOSUB HappyWorm
IF lvl>=5 % after level 5, reward player with a mix of green/gold tiles
PAUSE 400
FOR nt=1 TO FLOOR(2*RND()+1)
x=0: y=0: GOSUB FindFreeTile % find free tile anywhere in the board
IF !FLOOR(2*RND()) THEN GOSUB CreateGreenTile ELSE GOSUB CreateGoldTile
Render()
NEXT
ENDIF
ELSEIF bonusidx & submit>=bonusreminder % reminder for bonus word every N submit (N=5,10,15,20)
submit=0 % reset reminder
bonusreminder=MIN(20, bonusreminder+5) % increase time for next reminder, up to 20 max
Dlg7:
tit$=Label$("dlg7title")
msg$=Label$("dlg7msg")
btn1$=Label$("dlg7btn")
btn2$=""
GOSUB DialogMessage
IF debug THEN RETURN
IF inbgnd: GOSUB SaveGame: EXIT: ENDIF
ENDIF
ELSEIF LEN(mot$) % invalid word
IF !mute THEN SOUNDPOOL.PLAY sid, snd+20
GOSUB ResetSel
Render()
ENDIF
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NextBonusWord:
% Cycle through the list of bonus words
ARRAY.LENGTH al, bonusword$[]
IF !bonusidx
bonusletters=3
bonusidx=2
GOSUB LoadBonusWords
ELSEIF bonusidx>=al
bonusletters++
IF bonusletters>4 THEN bonusletters=3
bonusidx=1
GOSUB LoadBonusWords
ELSE
bonusidx++
ENDIF
bonus$=bonusword$[bonusidx]
% Animate bonus word change
PAUSE 300
IF !mute THEN SOUNDPOOL.PLAY sid, snd+1
GR.MODIFY ptrwrm, "bitmap", bmpwrm+1
GR.MODIFY txbonus, "text", bonus$: GR.MODIFY txbonus+1, "text", bonus$
FOR x=104 TO 554 STEP (554-104)/anim
GR.MODIFY txbonus, "x", x
GR.MODIFY txbonus+1, "x", x
Render()
NEXT
GR.MODIFY ptrwrm, "bitmap", bmpwrm+2*(danger>0): Render()
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LoadBonusWords:
CheckExist(INT$(bonusletters)+"_letter_words_"+gLng$+".txt")
GRABFILE bonus$, INT$(bonusletters)+"_letter_words_"+gLng$+".txt"
ARRAY.DELETE bonusword$[]
SPLIT bonusword$[], bonus$, "\n"
bonus$=""
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HappyWorm:
% Animation when changing level
FOR i=1 TO 2
IF !mute THEN SOUNDPOOL.PLAY sid, snd+21,0.99,0.99
GR.MODIFY ptrwrm, "bitmap", bmpwrm+1: Render(): PAUSE 100
GR.MODIFY ptrwrm, "bitmap", bmpwrm+2*(danger>0): Render(): PAUSE 100
NEXT
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FindFreeTile:
% find a free tile in row y or column x
security=0
IF !y
IF !x THEN x=FLOOR(7*RND()+1)
y=FLOOR(7*RND()+1)
WHILE security<8 & tiltyp[x,y]: y=1+MOD(y+3+INT(2*RND()),7): security++: REPEAT
ELSEIF !x
x=FLOOR(7*RND()+1)
WHILE security<8 & tiltyp[x,y]: x=1+MOD(x+3+INT(2*RND()),7): security++: REPEAT
ENDIF
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ONTIMER:
% Thread routine to update the score after submitting a word
tmpscore=10*INT((score+0.5*worth*scoranim/anim)/10)
GR.MODIFY txscore, "text", INT$(tmpscore)
GR.MODIFY txscore+1, "text", INT$(tmpscore)
progress=1+MIN(24, INT(24*(tmpscore-pvlvl)/(nxlvl-pvlvl)))
GR.MODIFY ptrprogress, "left", progress[progress]
IF MOD(scoranim,6)=0
GR.MODIFY txscore, "y", y0+925
GR.MODIFY txscore+1, "y", y0+925
ELSEIF MOD(scoranim,6)=1
GR.MODIFY txscore, "y", y0+930
GR.MODIFY txscore+1, "y", y0+930
ENDIF
Render()
scoranim++
IF scoranim>2*anim % reached last animation step
TIMER.CLEAR
score+=worth
ENDIF
TIMER.RESUME
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FallAndFill:
% Routine when tile @(x,y) disappears
% 1. make all tiles above fall
FOR yy=y TO 6
scrabble$[7*(x-1)+yy]=scrabble$[7*(x-1)+yy+1]
e$=scrabble$[7*(x-1)+yy]: IF e$="Q" THEN e$="Qu"
GR.MODIFY txletr+7*(x-1)+yy-1, "text", e$
tiltyp[x,yy]=tiltyp[x,yy+1]
GR.MODIFY ptrtil+7*(x-1)+yy-1, "bitmap", bmptil+tiltyp[x,yy]
NEXT
IF !danger & y=1 & tiltyp[x,y]=1 THEN danger=3
% 2. then fill empty location at the top with a spare tile
ARRAY.SHUFFLE spare$[] % shuffle spare tiles
scrabble$[7*(x-1)+7]=spare$[7*(x-1)+7]
e$=scrabble$[7*(x-1)+7]: IF e$="Q" THEN e$="Qu"
GR.MODIFY txletr+7*(x-1)+6, "text", e$
tiltyp[x,7]=0
GR.MODIFY ptrtil+7*(x-1)+6, "bitmap", bmptil+tiltyp[x,7]
% 3. finally, push the swallowed letter back into the spare tiles
spare$[7*(x-1)+7]=swallowed$ % (at the place where we pulled one)
% Warn user when a hot tile has reached the bottom of the board
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ConsumeHotTiles:
consumed=0: gameover=0
FOR x=1 TO 7
IF tiltyp[x,1]=1 & danger=1 THEN gameover=1
FOR y=1 TO 6
IF tiltyp[x,y+1]=1
IF !consumed: consumed=1: PAUSE 500: ENDIF
IF y=1 & !danger THEN danger=3
IF !mute
VIBRATE vibr[], -1
SOUNDPOOL.PLAY sid, snd+3,0.99,0.99
ENDIF
FOR j=1 TO anim % make fire tile fall
GR.MODIFY ptrtil+7*(x-1)+y, "y", y0+173+(6-y)*91+40*MOD(x-1,2)+j*91/anim
GR.MODIFY txletr+7*(x-1)+y, "y", y0+237+(6-y)*91+40*MOD(x-1,2)+j*91/anim
Render()
NEXT
GR.MODIFY ptrtil+7*(x-1)+y, "y", y0+173+(6-y)*91+40*MOD(x-1,2)
GR.MODIFY txletr+7*(x-1)+y, "y", y0+237+(6-y)*91+40*MOD(x-1,2)
swallowed$=scrabble$[7*(x-1)+y]
GOSUB FallAndFill
Render()
ENDIF
NEXT
NEXT
GR.SHOW ptrhot: GOSUB ResetHot
% Warn user when a hot tile has reached the bottom of the board
IF danger=3 THEN GOSUB ShowDanger
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ShowDanger:
danger=2
PAUSE 300
i=10+FLOOR(3*RND()): IF i>10 THEN i+=3
IF !mute THEN SOUNDPOOL.PLAY sid, snd+i
GR.MODIFY ptrwrm, "bitmap", bmpwrm+2: Render()
Dlg8:
tit$=Label$("dlg8title")
msg$=Label$("dlg8msg")
btn1$=Label$("dlg8btn")
btn2$=""
GOSUB DialogMessage
IF debug THEN RETURN
IF inbgnd: GOSUB SaveGame: EXIT: ENDIF
RETURN
%==========================================================
WaitInput:
touched=0: shaken=0: backkey=0: inbgnd=0
c0=CLOCK()
DO
PAUSE 10
GR.TOUCH touched, x, y
IF detectshake
SENSORS.READ 1, s10, s11, s12
shaken=( (s10-s20)^2 ~
+(s11-s21)^2 ~
+(s12-s22)^2 ~
>100 )
ENDIF
UNTIL touched | shaken | backkey | inbgnd ~
| (delay>0 & CLOCK()-c0>delay)
IF shaken
s20=s10: s21=s11: s22=s12
ELSEIF touched
x/=sw: y=(y-y0)/sh
ENDIF
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WaitRelease:
touched=1: backkey=0: inbgnd=0
c0=CLOCK()
DO
PAUSE 10
GR.TOUCH touched, x, y
x/=sw: y=(y-y0)/sh
UNTIL !touched | backkey | inbgnd ~
| (delay>0 & CLOCK()-c0>delay)
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ONBACKKEY:
backkey=1
BACK.RESUME
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ONBACKGROUND:
inbgnd=1
BACKGROUND.RESUME
%==========================================================
CheckResources:
LIST.CREATE s, resource
TEXT.OPEN r, fid, "all.res"
IF fid<0 THEN Fatal("Missing 'all.res' file")
allresok=1
DO
TEXT.READLN fid, e$: e$=TRIM$(e$)
IF e$="EOF" THEN D_U.BREAK
AddToList(resource, 1, e$)
FILE.EXISTS fe, e$: allresok*=fe
UNTIL 0
TEXT.CLOSE fid
LIST.SIZE resource, ls
ARRAY.DELETE resource$[]
LIST.TOARRAY resource, resource$[]
LIST.CLEAR resource
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LoadLabels:
CheckAndDL("labels_"+mLng$+".txt")
TEXT.OPEN r, fid, "labels_"+mLng$+".txt"
DO % Load menus labels
TEXT.READLN fid, e$: e$=TRIM$(e$)
IF e$="EOF" THEN D_U.BREAK
i=IS_IN("=", e$)
IF i & LEFT$(e$,1)<>"#" THEN BUNDLE.PUT global, LOWER$(LEFT$(e$, i-1)), REPLACE$(MID$(e$, i+1), "\\n", "\n")
UNTIL 0
TEXT.CLOSE fid
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LoadScrabble:
LIST.CREATE s, scrabble
CheckAndDL("letters_"+gLng$+".txt")
TEXT.OPEN r, fid, "letters_"+gLng$+".txt"
DO
TEXT.READLN fid, e$: e$=TRIM$(e$)
IF e$="EOF" THEN D_U.BREAK
i=IS_IN(" ", e$)
IF i & LEFT$(e$,1)<>"#"
AddToList(scrabble, VAL(LEFT$(e$, i-1)), MID$(e$, i+1, 1))
BUNDLE.PUT global, "val("+MID$(e$, i+1, 1)+")", VAL(TRIM$(MID$(e$, i+2)))
ENDIF
UNTIL 0
TEXT.CLOSE fid
LIST.SIZE scrabble, ls
IF ls<49*2
Fatal("Not enough scrabble tiles!\n(at least 98 are necessary)")
ENDIF
ARRAY.DELETE scrabble$[]
LIST.TOARRAY scrabble, scrabble$[]
LIST.CLEAR scrabble
% First 49 elements of scrabble$[] are the 49 tiles of the board,
% starting bottom left, going up, then right.
% The remaining is used as spare tiles for when user submits a word
ARRAY.DELETE spare$[]
DIM spare$[ls-49]
ARRAY.COPY scrabble$[50], spare$[]
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SaveConfig:
TEXT.OPEN w, fid, "bookworm.cfg"
TEXT.WRITELN fid, mLng$ % menus language
TEXT.WRITELN fid, gLng$ % game language
TEXT.WRITELN fid, INT$(mute)
TEXT.CLOSE fid
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SaveGame:
TEXT.OPEN w, fid, "bookworm.sav"
TEXT.WRITELN fid, INT$(lvl)
TEXT.WRITELN fid, INT$(score)
TEXT.WRITELN fid, INT$(bonusletters)
TEXT.WRITELN fid, INT$(bonusidx)
JOIN scrabble$[], scrabble$, ","
TEXT.WRITELN fid, scrabble$
tt$=""
FOR sgx=1 TO 7
FOR sgy=1 TO 7
tt$+=INT$(tiltyp[sgx,sgy])+","
NEXT
NEXT
TEXT.WRITELN fid, LEFT$(tt$, -1)
TEXT.WRITELN fid, INT$(highest)
TEXT.WRITELN fid, highest$
TEXT.WRITELN fid, longest$
TEXT.CLOSE fid
POPUP Label$("saved")
RETURN
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LoadGame:
TEXT.OPEN r, fid, "bookworm.sav"
IF !fid THEN RETURN
TEXT.READLN fid, lg$: lvl=VAL(lg$)
TEXT.READLN fid, lg$: score=VAL(lg$)
TEXT.READLN fid, lg$: bonusletters=VAL(lg$)
TEXT.READLN fid, lg$: bonusidx=VAL(lg$)
TEXT.READLN fid, scrabble$
ARRAY.DELETE scrabble$[]
SPLIT scrabble$[], scrabble$, ","
ARRAY.COPY scrabble$[50], spare$[]
TEXT.READLN fid, tiltyp$
SPLIT tiltyp$[], tiltyp$, ","
FOR lgx=1 TO 7
FOR lgy=1 TO 7
tiltyp[lgx,lgy]=VAL(tiltyp$[7*(lgx-1)+lgy])
NEXT
NEXT
ARRAY.DELETE tiltyp$[]
TEXT.READLN fid, lg$: highest=VAL(lg$)
TEXT.READLN fid, highest$
TEXT.READLN fid, longest$
TEXT.CLOSE fid
RETURN
%==========================================================
DialogMessage:
% Create empty book
IF bmpdlg THEN GR.BITMAP.DELETE bmpdlg
GR.BITMAP.CREATE bmpdlg, 590, 637
GR.BITMAP.DRAWINTO.START bmpdlg
GR.BITMAP.DRAW nul, bmpopb, 0, 0
% Write title
GR.TEXT.ALIGN 2 % centered
SetColor("fff8ff01"): gPrint(295,100,50,tit$,"ff000000",fnt3)
IF debug
GR.TEXT.ALIGN 1 % left
SetColor("ffff01f8")
gPrint(20,35,25,"(Dlg#"+INT$(dl)+")","ff000000",fnt3)
GR.TEXT.ALIGN 2 % centered
ENDIF
SetColor("ff000000"): GR.TEXT.SETFONT fnt4
IF !dsz THEN dsz=44
GR.TEXT.SIZE dsz
GR.TEXT.BOLD 1
SPLIT msg$[], msg$, "\n"
ARRAY.LENGTH al, msg$[]
% Then write message
dy=130-20*(LEN(msg$)>99)
FOR di=1 TO al
IF !LEN(msg$[di]) THEN dy=100
GR.TEXT.DRAW nul, 295, dy+70*di, msg$[di]
NEXT
ARRAY.DELETE msg$[]
SetColor("ff7f0000")
GR.TEXT.SETFONT "Normal": GR.TEXT.SIZE 26
% Finally write button(s)
IF LEN(btn2$)
GR.BITMAP.DRAW nul, bmpbtn, 36, 520
GR.TEXT.DRAW nul, 155, 560, btn1$
GR.BITMAP.DRAW nul, bmpbtn, 316, 520
GR.TEXT.DRAW nul, 435, 560, btn2$
ELSE
GR.BITMAP.DRAW nul, bmpbtn, 175, 520
GR.TEXT.DRAW nul, 294, 560, btn1$
ENDIF
GR.TEXT.BOLD 0
GR.BITMAP.DRAWINTO.END
% Update/create the layer in the display list
IF ptrdlg
GR.MODIFY ptrdlg, "bitmap", bmpdlg, "y", y0+973
GR.SHOW ptrdlg
ELSE
GR.BITMAP.DRAW ptrdlg, bmpdlg, 24, y0+973
ENDIF
% Make the dialog appear from bottom of screen
IF !mute THEN SOUNDPOOL.PLAY sid, snd+18,0.99,0.99
FOR di=973 TO 173 STEP -80
GR.MODIFY ptrdlg, "y", y0+di: Render()
NEXT
btn1=0: btn2=0: dsz=0
delay=-1: detectshake=0 % infinite (blocking) WaitInput and WaitRelease
% Wait for good user feedback: back key or home key or touch on button(s)
DO
GOSUB WaitInput
IF touched
IF LEN(btn2$) & x>24+36 & x<24+36+234 & y>173+520 & y<173+520+100 THEN btn1=1
IF LEN(btn2$) & x>24+316 & x<24+316+234 & y>173+520 & y<173+520+100 THEN btn2=1
IF !LEN(btn2$) & x>24+175 & x<24+175+234 & y>173+520 & y<173+520+100 THEN btn1=1
ENDIF
UNTIL backkey | inbgnd | btn1 | btn2
IF debug & backkey THEN END "Done."
% Make the dialog disappear to bottom of screen
IF !inbgnd
IF !mute THEN SOUNDPOOL.PLAY sid, snd+18,0.99,0.99
GOSUB WaitRelease
FOR di=173 TO 973 STEP 80
GR.MODIFY ptrdlg, "y", y0+di: Render()
NEXT
GR.HIDE ptrdlg: Render()
ENDIF
SetColor("ff0000ff"): GR.SET.STROKE 10 % for word-lines
RETURN