3 Copyright
2008, 2018 Pajo
<xpio at tut dot by
>
5 This program is free software
: you can redistribute it
and/or modify
6 it under the terms of the GNU General
Public License
as published by
7 the Free Software Foundation
, either version
3 of the License
, or
8 (at your
option) any later version
.
10 This program is distributed
in the hope that it will be useful
,
11 but WITHOUT ANY WARRANTY
; without even the implied warranty of
12 MERCHANTABILITY
or FITNESS
FOR A PARTICULAR PURPOSE
. See the
13 GNU General
Public License
for more details
.
15 You should have received a copy of the GNU General
Public License
16 along
with this program
. If not, see
<https
://www
.gnu
.org
/licenses
/>.
25 const VARPATH
="variations"
26 Dim Shared
As String nextvariation
, title
27 ReDim Shared
help () As String
28 Dim Shared
As UByte playabletiles
, numberoftiles
29 Dim Shared
As Short columns
=1, rows
=1
30 Dim Shared
As Byte wrap
,gravity
,randominputs
,randomgoals
,showscore
=FALSE
31 dim shared score
as short
=0
32 ReDim Shared
tilesfiles(0) As String
33 Dim Shared speed
as single=3
34 ReDim Shared
randomtable() As UByte
35 Dim Shared tim
as Double
37 Declare Function loadgame(filename
As String) As Byte
38 Declare Sub loadTiles(increment
As Byte=1)
39 Declare Sub initplayfield()
41 Function asctonumber(ch
As UByte
) As UByte
42 If ch
=46 Then : Return 0
43 ElseIf ch
=33 Then : Return 254 'start=!=254
44 ElseIf ch
=Asc("@") Then : Return 253 'exit=@=253
45 ElseIf ch
>=48 And ch
<=57 Then : Return ch
-48
46 ElseIf ch
>=65 And ch
<=90 Then : Return ch
-65+10
47 ElseIf ch
>=97 And ch
<=122 Then : Return ch
-97+36
52 Function getImgWidth(filename
As String) As Short
53 Open filename
For Input
As #
2
54 If Err
>0 Then Return 0
61 ReDim Shared
inputsindex(0) As UByte
'pokazuje krajeve
62 ReDim Shared
inputs(0,2) As UByte
63 ReDim Shared
goals(0,2) As UByte
64 Sub loadshapes(shapes() As UByte
, filename
As String, index
As Byte=FALSE)
66 Dim currentpoint
As Short
=0
67 Dim As UByte a
,b
=0,currentshape
=0
68 Do Until l
="}" Or Eof(1)
72 shapes(currentpoint
,0)=255
73 shapes(currentpoint
,1)=255
74 shapes(currentpoint
,2)=255 'end shape
76 ReDim Preserve inputsindex(currentshape
)
77 inputsindex(currentshape
)=currentpoint
81 ReDim Preserve shapes(currentpoint
,2)
84 shapes(currentpoint
,0)=a
85 shapes(currentpoint
,1)=b
86 If l
[a
]=46 Then : shapes(currentpoint
,2)=0
87 Else : shapes(currentpoint
,2)=asctonumber(l
[a
])
90 ReDim Preserve shapes(currentpoint
,2)
95 shapes(currentpoint
,0)=255
96 shapes(currentpoint
,1)=255
97 shapes(currentpoint
,2)=255 'end shape
99 ReDim Preserve inputsindex(currentshape
)
100 inputsindex(currentshape
)=currentpoint
105 Declare Sub gameOver()
107 dim shared
playfield(0 to columns
-1,0 to rows
-1) as UByte
108 dim shared
originalplayfield(0 to columns
-1,0 to rows
-1) as UByte
113 Declare sub update(justerase
As Byte = FALSE)
115 Declare Function move(as Byte,as Byte=0,As UByte
=0) As Byte
118 Declare Function isblocked(x
as Byte, y
As Byte=0, typ
As UByte
=0, mode
As Byte=FALSE) As Byte
119 As Short x
,y
,oldx
,oldy
123 ReDim Shared
nextshape() As UByte
125 Function block
.isblocked(x
as Byte, y
As Byte=0, typ
As UByte
=0, mode
As Byte=FALSE) As Byte
126 Dim As Short strt
, stp
, a
129 If typ
=1 Then strt
=0 Else strt
=inputsindex(typ
-1-1)+1 'preskace se ona 255 tacka
130 stp
=inputsindex(typ
-1)-1 'izostavlja se ona 255 tacka
131 'mode=true = ispituje se origin
133 failed
=inputs(a
,2)<>0 And _
134 playfield(x
+inputs(a
,0),y
+inputs(a
,1))<>254 And _
135 playfield(x
+inputs(a
,0),y
+inputs(a
,1))<>253
136 If Not mode
Then failed
=failed
And playfield(x
+inputs(a
,0),y
+inputs(a
,1))<>0
137 failed
=failed
Or y
+inputs(a
,1)>=rows _
139 Or x
+inputs(a
,0)>=columns _
141 If failed
Then Exit For
148 If randominputs
Then 'permutovati brojeve od 1 do playabletiles
150 ReDim randomtable(playabletiles
) As UByte
151 For a
= 1 To playabletiles
152 randomtable(a
)=fix(rnd
*playabletiles
)+1
159 ReDim startpositions(0) As xy
160 Dim posnumber
As UShort
=0
162 Dim starttyp
As UByte
163 this
.typ
=fix(rnd
*(ubound(inputsindex
)+1))+1
166 for y
=0 to rows
-1 : for x
=0 to columns
-1
167 If originalplayfield(x
,y
)=254 Then
168 If Not this
.isblocked(x
,y
,this
.typ
,TRUE) Then 'dodaj na listu
169 ReDim Preserve startpositions(posnumber
) As xy
170 startpositions(posnumber
)=Type(x
,y
)
176 this
.typ
=nextshape(this
.typ
)
177 If this
.typ
=starttyp
Then
182 Loop Until posnumber
>0
183 posnumber
=fix(rnd
*posnumber
)
184 this
.x
=startpositions(posnumber
).x
185 this
.y
=startpositions(posnumber
).y
192 'constructor bi se pokretao kod samog deklarisanja, pre playfielda
195 Function getshapewidthheight(typ
As UByte
,geth
As Byte = FALSE) As Short
196 Dim As Short strt
, stp
, a
, maxwidth
=0, maxheight
=0
198 If typ
=1 Then strt
=0 Else strt
=inputsindex(typ
-1-1)+1 'preskace se ona 255 tacka
199 stp
=inputsindex(typ
-1)-1 'izostavlja se ona 255 tacka
201 If maxwidth
<inputs(a
,0) Then maxwidth
=inputs(a
,0)
202 If maxheight
<inputs(a
,1) Then maxheight
=inputs(a
,1)
204 If geth
Then Return maxheight
209 Function block
.move(x
as Byte, y
As Byte=0, typ
As UByte
=0) As Byte 'successfull?true/false
215 dw
=(getshapewidthheight(this
.typ
)-getshapewidthheight(typ
)) / 2
219 dh
=(getshapewidthheight(this
.typ
,TRUE)-getshapewidthheight(typ
,TRUE)) / 2
225 this
.update(TRUE) 'just erase oldx i oldy
227 this
.x
=x
+ this
.x
+ dw
228 this
.y
=y
+ this
.y
+ dh
230 this
.x
=(this
.x
+ columns
) Mod columns
231 If Not gravity
Then this
.y
=(this
.y
+ rows
) Mod rows
234 failed
=failed
Or y
+inputs(a
,1)>=rows _
236 Or x
+inputs(a
,0)>=columns _
241 failed
=this
.isblocked(this
.x
,this
.y
,typ
)
255 Sub markshape(shapestart
As Short
,shapeend
As Short
,x
As Short
,y
As Short
)
257 For q
=shapestart
To shapeend
-1
260 If goals(q
,2)<>0 And playfield(mx
,my
)<100 Then
261 playfield(mx
,my
)+=100
267 function matchshape(x
As Short
,y
As Short
) as Byte
268 dim as Byte fullshape
,foundshape
=FALSE
269 Dim As Short mx
,my
,shapestart
=0,p
=0,q
271 Dim goalscolors(100) As UByte
'za randomgoals '!max 100 randomgolova
273 For p
=0 To UBound(goals
)
274 If goals(p
,0)=255 And goals(p
,1)=255 And goals(p
,2)=255 Then '255,255,255=end
275 If fullshape
=TRUE Then
276 markshape(shapestart
,p
,x
,y
)
281 For a
=0 To UBound(goalscolors
) : goalscolors(a
)=0 : Next a
285 If mx
<0 Or mx
>columns
-1 Or my
<0 Or my
>rows
-1 Then
287 ElseIf goals(p
,2)=255 Then '255=joker
288 fullshape
= fullshape
And _
289 (playfield(mx
,my
)<>0) And _
290 (playfield(mx
,my
)<>254) And _
291 (playfield(mx
,my
)<>253)
292 ElseIf goals(p
,2)<>0 Then
294 If goalscolors(goals(p
,2))=0 Then
295 If (playfield(mx
,my
)<>0) And _
296 (playfield(mx
,my
)<>254) And _
297 (playfield(mx
,my
)<>253)Then
298 goalscolors(goals(p
,2))=playfield(mx
,my
)
303 fullshape
= fullshape
And (playfield(mx
,my
)=goalscolors(goals(p
,2)) _
304 Or playfield(mx
,my
)=goalscolors(goals(p
,2))+100)
306 fullshape
= fullshape
And (playfield(mx
,my
)=goals(p
,2) _
307 Or playfield(mx
,my
)=goals(p
,2)+100)
317 dim as byte x
,y
,gap
,removed=false,scoremulti=0,existsnextvariation=FALSE, gotonextvariation=TRUE
318 for y
=0 to rows
-1 : for x
=0 to columns
-1
319 if matchshape(x
,y
) then scoremulti
+=1
321 If gravity
Then 'remove >100 (marked shapes)
324 for y
=rows
-1 to 0 step
-1
325 if playfield(x
,y
)>100 And playfield(x
,y
)<>254 And playfield(x
,y
)<>253 Then
328 If playfield(x
,y
)=254 Then
329 If originalplayfield(x
,y
)=254 Or originalplayfield(x
,y
)=253 Then
330 playfield(x
,y
+gap
)=originalplayfield(x
,y
)
334 Else playfield(x
,y
+gap
)=playfield(x
,y
)
338 If originalplayfield(x
,y
)=254 Or originalplayfield(x
,y
)=253 Then
339 playfield(x
,y
)=originalplayfield(x
,y
)
345 removed=removed or gap>0
347 if removed then checksituation()
349 for y
=0 to rows
-1 : for x
=0 to columns
-1
350 if playfield(x
,y
)>100 And playfield(x
,y
)<>254 And playfield(x
,y
)<>253 Then
351 If originalplayfield(x
,y
)=254 Or originalplayfield(x
,y
)=254 Then
352 playfield(x
,y
)=originalplayfield(x
,y
)
360 'proveri da li je pokriven exit
361 for y
=0 to rows
-1 : for x
=0 to columns
-1
362 If originalplayfield(x
,y
)=253 Then
363 existsnextvariation
=TRUE
364 If playfield(x
,y
)=253 Then gotonextvariation
=FALSE
367 If existsnextvariation
And gotonextvariation
Then
368 loadgame(VARPATH
+"/"+nextvariation
)
376 Sub block
.update(justerase
As Byte =FALSE)
377 Dim As Short strt
, stp
, a
379 If this
.oldtyp
=1 Then strt
=0 Else strt
=inputsindex(this
.oldtyp
-1-1)+1 'preskace se ona 255 tacka
380 stp
=inputsindex(this
.oldtyp
-1)-1 'izostavlja se ona 255 tacka
382 If inputs(a
,2)<>0 Then
383 If originalplayfield(this
.oldx
+inputs(a
,0),this
.oldy
+inputs(a
,1))=254 Or _
384 originalplayfield(this
.oldx
+inputs(a
,0),this
.oldy
+inputs(a
,1))=253 Then
385 playfield(this
.oldx
+inputs(a
,0),this
.oldy
+inputs(a
,1)) = _
386 originalplayfield(this
.oldx
+inputs(a
,0),this
.oldy
+inputs(a
,1)) 'cuvamo "start" pri pomeranju
388 playfield(this
.oldx
+inputs(a
,0),this
.oldy
+inputs(a
,1))=0
392 If justerase
=FALSE Then
393 If this
.typ
=1 Then strt
=0 Else strt
=inputsindex(this
.typ
-1-1)+1 'preskace se ona 255 tacka
394 stp
=inputsindex(this
.typ
-1)-1 'izostavlja se ona 255 tacka
396 If inputs(a
,2)<>0 Then
398 playfield(this
.x
+inputs(a
,0),this
.y
+inputs(a
,1))=randomtable(inputs(a
,2))
400 playfield(this
.x
+inputs(a
,0),this
.y
+inputs(a
,1))=inputs(a
,2)
407 ' playfield(this.oldx,this.oldy)=0
408 ' playfield(this.x,this.y)=this.typ
414 If Not this
.move(0,1) Then
419 nije mi jasno kako checksituation funkcionise bez ovoga
:
425 dim keypress
as string
428 ReDim playfield(0 to columns
-1,0 to rows
-1) As UByte
430 for y
=0 to rows
-1 : for x
=0 to columns
-1
431 playfield(x
,y
)=originalplayfield(x
,y
)
436 Dim Shared tilewidth
As Short
437 Dim Shared tilesimg
As Any Ptr
438 Dim Shared scoreimg
As Any Ptr
440 Declare Sub drawplayfield()
442 Sub loadTiles(increment
As Byte=1)
443 Static tilesetnum
As UByte
444 tilesetnum
+=increment
445 If tilesetnum
>UBound(tilesfiles
) Then tilesetnum
=0
446 If tilesetnum
<0 Then tilesetnum
= UBound(tilesfiles
)
448 Dim tilesfile
As String
449 tilesfile
=GFXPATH
& "/" & tilesfiles(tilesetnum
)
450 tilewidth
= getImgWidth(tilesfile
)
452 ScreenRes tilewidth
*columns
,tilewidth
*rows
+16,16,2',&h08
454 ScreenRes tilewidth
*columns
,tilewidth
*rows
,16,2',&h08
458 tilesimg
= ImageCreate(tilewidth
, tilewidth
*(3+numberoftiles
))
459 BLoad tilesfile
, tilesimg
460 scoreimg
= ImageCreate(122,20)
461 BLoad GFXPATH
+"/brojke.bmp", scoreimg
465 dim shared blok
as block
468 'ScreenRes tilewidth*columns,tilewidth*rows,16,2,&h08
470 Dim As Byte numberstarted
=FALSE
472 Static xpx
As UByte
= 0
473 Line (0,0)-(xpx
,14),RGB(0,0,0),bf
475 For a
=0 To 8 'max 9 digits
476 digit
=Fix((score Mod
10^
(9-a
)) / 10^
(8-a
))
477 numberstarted
=numberstarted
Or digit
>0
478 If numberstarted
Then
480 Put (1+xpx
,1),scoreimg
,(13,0)-(17,14),PSet
483 Put (1+xpx
,1),scoreimg
,(0,0)-(12,14),PSet
486 Put (1+xpx
,1),scoreimg
,(-8+digit
*13,0)-(-8+12+digit
*13,14),PSet
492 Dim xpx
As UShort
= tilewidth
*columns
493 Line(0,0)-(xpx
,16),RGB(0,0,0),BF
494 For a
=0 To 9 'max 10 digits - traze se otpozadi
495 If 10^a
> score
Then Exit For
496 digit
=Fix((score Mod
10^
(a
+1)) / 10^a
)
499 Put (xpx
,1),scoreimg
,(13,0)-(17,14),PSet
502 Put (xpx
,1),scoreimg
,(0,0)-(12,14),PSet
505 Put (xpx
,1),scoreimg
,(-8+digit
*13,0)-(-8+12+digit
*13,14),PSet
512 Dim As Short offsetx
=0,offsety
=0,offsetpx
=0,offsetpy
=0
513 If showscore
Then offsetpy
=16
515 for y
=0 to rows
-1 : for x
=0 to columns
-1
516 If playfield(x
,y
)=0 Then : t
=0
517 ElseIf playfield(x
,y
)=254 Then : t
=1
518 ElseIf playfield(x
,y
)=253 Then : t
=2
519 Else : t
=playfield(x
,y
)+2
521 Put (offsetpx
+(offsetx
+x
)*tilewidth
, offsetpy
+(offsety
+y
)*tilewidth
), _
522 tilesimg
,(0,t
*tilewidth
) - Step(tilewidth
-1,tilewidth
-1),PSet
524 If showscore
Then drawscore
532 Dim l
As String, n
As UByte
=0
533 Do Until l
="}" Or Eof(1)
535 ReDim Preserve tilesfiles(n
)
539 ReDim Preserve tilesfiles(n
-2)
544 Dim l
As String, n
As UByte
546 ReDim nextshape(Len(l
)) As UByte
547 For n
=0 To Len(l
) 'nextshape(0) se ne koristi
548 nextshape(n
+1)=asctonumber(l
[n
])
555 Dim l
As String, n
As UByte
556 Dim position
As Integer = Seek(1)
558 Do Until l
="}" Or Eof(1)
561 If Len(l
)>columns
Then columns
=Len(l
)
563 ReDim originalplayfield(0 to columns
-1,0 to rows
-1) as UByte
567 Do Until l
="}" Or Eof(1)
572 If l
[a
]=46 Then : originalplayfield(a
,b
-1)=0
573 Else : originalplayfield(a
,b
-1)=asctonumber(l
[a
])
577 originalplayfield(a
,b
-1)=n
578 If n
>numberoftiles
And n
<100 Then numberoftiles
=n
581 If playabletiles
>numberoftiles
Then numberoftiles
=playabletiles
591 Do Until l
="}" Or Eof(1)
593 wrap
=wrap
Or l
="wrap"
594 gravity
=gravity
Or l
="gravity"
595 randominputs
=randominputs
Or l
="randominputs"
596 randomgoals
=randomgoals
Or l
="randomgoals"
597 If Left(l
,6)="tiles:" Then playabletiles
=CInt(Mid(l
,7))
612 Function readtitle(filename
As String) As String
613 Dim As String l
, result
614 Open filename
For Input
As #
1
615 If Err
>0 Then Print
"Error opening the file":End
633 If l
="}" Then Exit Do
634 ReDim Preserve help(UBound(help
) + 1)
635 help(UBound(help
)) = l
640 Function loadgame(filename
As String) As Byte
641 If filename
= "" Then Return FALSE
643 Open filename
For Input
As #
1
644 If Err
>0 Then Print
"Error opening the file":End
655 Line Input #
1,nextvariation
661 loadshapes(inputs(),filename
,TRUE)
665 loadshapes(goals(),filename
)
677 Function isin(xx
As Short
,yy
As Short
,x
As Short
,y
As Short
,w
As UShort
=50,h
As UShort
=50) As Byte
678 Dim in As Byte = TRUE
679 in=in And xx
>=x
And xx
<=x
+w
680 in=in And yy
>=y
And yy
<=y
+h
686 showscore
=Not showscore
688 ScreenRes tilewidth
*columns
,tilewidth
*rows
+16,16,2',&h08
690 ScreenRes tilewidth
*columns
,tilewidth
*rows
,16,2',&h08
698 ImageDestroy(tilesimg
)
699 ImageDestroy(scoreimg
)
704 Sub openwindow(s
As Sub)
710 ScreenRes w
,h
,16,2',&h08
715 Function openloader(directory
As String) As String
717 ScreenRes
300,150,16,1',&h08
719 Print
"Load Variation"
723 Dim filenames (1 To 9) As String
726 filenames(n
) = Dir(directory
+ "/*")
727 Do While n
<= 9 and Len(filenames(n
))
728 title
= readtitle(directory
+ "/" + filenames(n
))
729 Print n
; ". " ; title
735 Print
"Press number to load variation"
736 Print
"or any other key to exit."
739 Dim keypress
As String
742 Loop Until keypress
<> ""
743 If Val(keypress
) >= 1 And Val(keypress
) <= 9 Then
744 Return directory
+ "/" + filenames(Val(keypress
))
750 ScreenRes
300,150,16,1',&h08
752 Print
"Help for " + title
756 For a
= 0 To UBound(help
)
760 Dim keypress
As String
763 Loop Until keypress
<> ""
769 Dim As Integer x
, y
, pressed
771 Dim menuimg
As Any Ptr
772 ScreenRes
150,150,16,1',&h08
773 menuimg
= ImageCreate(150,150)
774 BLoad GFXPATH
+"/menu.bmp", menuimg
775 Put(0,0),menuimg
,PSet
776 Dim keypress
as string
780 If (ScreenEvent(@e
)) Then
782 Case EVENT_MOUSE_BUTTON_PRESS
784 If e
.button
=2 Then Exit Do
787 If isin(x
,y
,0,0) Then 'help
788 keypress
= chr(255)+";" 'F1
789 ElseIf isin(x
,y
,100,0) Then 'quit
790 keypress
= chr(27) 'Esc
791 ElseIf isin(x
,y
,50,50) Then 'tiles
793 ElseIf isin(x
,y
,0,50) Then 'speed
795 ElseIf isin(x
,y
,100,50) Then 'score
797 ElseIf isin(x
,y
,50,0) Then 'restart
798 keypress
= chr(255)+"<" 'F2
799 ElseIf isin(x
,y
,0,100) Then 'load
803 Case EVENT_MOUSE_BUTTON_RELEASE
805 Case EVENT_MOUSE_MOVE
807 ScreenControl GET_WINDOW_POS
, x
, y
808 ScreenControl SET_WINDOW_POS
, x
+ e
.dx
, y
+ e
.dy
816 ImageDestroy(menuimg
)
823 ImageDestroy(menuimg
)
825 Case chr(255)+";" 'F1
826 openwindow(@openhelp
)
827 Case chr(255)+"<" 'F2
831 If loadgame(openloader(VARPATH
)) Then Exit Sub
833 ImageDestroy(menuimg
)
837 Loop Until keypress
<> ""
838 ImageDestroy(menuimg
)
844 Static pressed
As Integer=0
845 If (ScreenEvent(@e
)) Then
847 Case EVENT_MOUSE_BUTTON_PRESS
849 If e
.button
=2 Then openwindow(@openmenu
)
850 Case EVENT_MOUSE_BUTTON_RELEASE
852 Case EVENT_MOUSE_MOVE
854 ScreenControl GET_WINDOW_POS
, x
, y
855 ScreenControl SET_WINDOW_POS
, x
+ e
.dx
, y
+ e
.dy
863 Dim As Short offsety
=0, offsety2
=0
864 Dim As Byte inkeyemptied
=FALSE, scoredrawn
=FALSE
867 If showscore
Then offsety
=16
869 Dim keypress
as string
873 If Timer
-tim2
>0.5 Then
876 While InKey
<>"" : Wend 'prazni inkey tokom prvih pola sekunde
879 If offsety2
<tilewidth
*rows
+offsety
-6 Then
880 If Timer
-tim
>0.03 Then
882 Line (0,offsety2
)-(tilewidth
*columns
,offsety2
+6),RGB(0,0,0),BF
883 Put(tilewidth
*columns
/2-47/2,offsety2
+1),scoreimg
,(52,15)-(99,19),PSet
889 If offsety2
>20 And Not scoredrawn
Then
895 Loop Until keypress
<>""
903 If Not loadgame(Command
) Then
904 If Not loadgame(openloader(VARPATH
)) Then End
909 if keypress
=chr(255)+"K" then
912 ElseIf keypress
=chr(255)+"M" then
915 ElseIf keypress
=" " Then
916 blok
.move(0,0,nextshape(blok
.typ
)) 'cycle
918 ElseIf keypress
=chr(255)+"H" Then 'move up or rotate
920 blok
.move(0,0,nextshape(blok
.typ
)) 'cycle
925 ElseIf keypress
=chr(255)+"P" Then 'down
935 ElseIf keypress
="t" Or keypress
="T" Then
937 ElseIf keypress
=Chr(13) Then 'enter=fix or drop
939 Do : score
+=1 : Loop While blok
.move(0,1)
945 ElseIf keypress
="s" Or keypress
="S" then 'score
947 ElseIf keypress
="l" Or keypress
="L" then 'load
948 loadgame(openloader(VARPATH
))
949 loadTiles(0) 'restore resolution
950 ElseIf keypress
=chr(255)+";" then 'F1
951 openwindow(@openhelp
)
952 ElseIf keypress
=chr(255)+"<" then 'F2
954 ElseIf keypress
="+" Then 'speed+
956 ElseIf keypress
=chr(27) Then 'Esc
957 openwindow(@openmenu
)
959 if gravity
And timer
-tim
>speed
then