INCLUDE "hug.bac", INIT, HUGOPTIONS, WINDOW, FRAME, CANVAS, KEY, TIMEOUT, PIXEL, MARK, TEXT, STOCK, ATTACH, DISPLAY, \
CALLBACK, QUIT, OUT, SQUARE, GRAB$, SHOW, HIDE, MSGDIALOG
CONST Xsize = 300
CONST Ysize = 300
CONST ENEMY_COL = 4
CONST TEMP_CHECK = -1
CONST TEMP_LINE = -2
CONST THRESHOLD = 75
CONST GAME_SPEED = 7
CONST GAME_STP = 0
CONST GAME_RUN = 1
CONST GAME_END = 2
DECLARE cach_board[Xsize][Ysize]
DECLARE real_board[Xsize][Ysize]
DECLARE me_board[Xsize][Ysize]
DECLARE enemy_board[Xsize][Ysize]
DECLARE xpos, ypos
DECLARE en_xpos[10], en_ypos[10], xoff[10], yoff[10]
DECLARE Game_State, Game_Level, Game_Lifes, Game_Score, Last_Color
DECLARE High_Score$
SUB Initialize_Game
LOCAL x, y
FOR x = 0 TO Xsize-1
FOR y = 0 TO Ysize-1
real_board[x][y] = 0
cach_board[x][y] = 0
me_board[x][y] = 0
enemy_board[x][y] = 0
NEXT
NEXT
SQUARE("#FFFFFF", 0, 0, Xsize, Ysize, TRUE)
FOR x = 2 TO Xsize-4
real_board[x][2] = 1
real_board[x][Ysize-4] = 1
NEXT
FOR y = 2 TO Ysize-4
real_board[2][y] = 1
real_board[Xsize-4][y] = 1
NEXT
xpos = Xsize/2
ypos = Ysize-3
FOR x = 0 TO Game_Level
en_xpos[x] = RANDOM(Xsize-50)+25
en_ypos[x] = RANDOM(50)+25
xoff[x] = RANDOM(2)+1
IF xoff[x] = 2 THEN xoff[x] = -1
yoff[x] = RANDOM(2)+1
IF yoff[x] = 2 THEN yoff[x] = -1
NEXT
CALL Draw_Me()
CALL Draw_Board()
Game_State = GAME_RUN
TEXT(mark1, "0%")
END SUB
SUB Draw_Board
LOCAL x, y
FOR x = 0 TO Xsize - 1
FOR y = 0 TO Ysize - 1
IF cach_board[x][y] <> real_board[x][y] THEN
cach_board[x][y] = real_board[x][y]
SELECT cach_board[x][y]
CASE 0
PIXEL("#FFFFFF", x, y)
CASE 1;
CASE TEMP_LINE
PIXEL("#000000", x, y)
CASE 2
PIXEL("#FF0000", x, y)
CASE 3
PIXEL("#00FF00", x, y)
CASE 4
PIXEL("#FFFF00", x, y)
CASE 5
PIXEL("#00FFFF", x, y)
CASE 6
PIXEL("#0000FF", x, y)
CASE 7
PIXEL("#FF00FF", x, y)
CASE 8
PIXEL("#FF0000", x, y)
END SELECT
END IF
SELECT me_board[x][y]
CASE 1
PIXEL("#000000", x, y)
cach_board[x][y] = 1
CASE 2
PIXEL("#FF0000", x, y)
cach_board[x][y] = 2
END SELECT
SELECT enemy_board[x][y]
CASE ENEMY_COL
PIXEL("#0000FF", x, y)
cach_board[x][y] = ENEMY_COL
END SELECT
NEXT
NEXT
END SUB
SUB Draw_Me
LOCAL x, y
FOR x = 0 TO Xsize-1
FOR y = 0 TO Ysize-1
me_board[x][y] = 0
NEXT
NEXT
me_board[xpos-2][ypos-2] = 1
me_board[xpos-1][ypos-2] = 1
me_board[xpos][ypos-2] = 1
me_board[xpos+1][ypos-2] = 1
me_board[xpos+2][ypos-2] = 1
me_board[xpos-2][ypos-1] = 1
me_board[xpos-1][ypos-1] = 2
me_board[xpos][ypos-1] = 2
me_board[xpos+1][ypos-1] = 2
me_board[xpos+2][ypos-1] = 1
me_board[xpos-2][ypos] = 1
me_board[xpos-1][ypos] = 2
me_board[xpos][ypos] = 2
me_board[xpos+1][ypos] = 2
me_board[xpos+2][ypos] = 1
me_board[xpos-2][ypos+1] = 1
me_board[xpos-1][ypos+1] = 2
me_board[xpos][ypos+1] = 2
me_board[xpos+1][ypos+1] = 2
me_board[xpos+2][ypos+1] = 1
me_board[xpos-2][ypos+2] = 1
me_board[xpos-1][ypos+2] = 1
me_board[xpos][ypos+2] = 1
me_board[xpos+1][ypos+2] = 1
me_board[xpos+2][ypos+2] = 1
END SUB
FUNCTION Fill_Area(NUMBER x, NUMBER y)
IF x < 0 OR x > Xsize-1 OR y < 0 OR y > Ysize-1 OR enemy_board[x][y] = ENEMY_COL THEN RETURN FALSE
IF real_board[x][y] <> 0 THEN
RETURN TRUE
ELSE
real_board[x][y] = TEMP_CHECK
END IF
IF NOT(Fill_Area(x+1, y)) THEN RETURN FALSE
IF NOT(Fill_Area(x-1, y)) THEN RETURN FALSE
IF NOT(Fill_Area(x, y+1)) THEN RETURN FALSE
IF NOT(Fill_Area(x, y-1)) THEN RETURN FALSE
RETURN TRUE
END FUNCTION
SUB Real_Fill(NUMBER color)
LOCAL x, y, percentage
FOR x = 0 TO Xsize-1
FOR y = 0 TO Ysize-1
IF real_board[x][y] = TEMP_CHECK THEN
real_board[x][y] = color
ELIF real_board[x][y] = TEMP_LINE THEN
real_board[x][y] = 1
ENDIF
IF real_board[x][y] = 1 OR real_board[x][y] >= 3 THEN INCR percentage
NEXT
NEXT
TEXT(mark1, STR$((percentage*100)/(Xsize*Ysize)) & "%")
END SUB
SUB Start_Fill
LOCAL color
REPEAT
color = RANDOM(6)+3
UNTIL color <> Last_Color
Last_Color = color
IF NOT(Fill_Area(xpos-1, ypos-1)) THEN
Real_Fill(0)
ELSE
Real_Fill(color)
END IF
IF NOT(Fill_Area(xpos+1, ypos-1)) THEN
Real_Fill(0)
ELSE
Real_Fill(color)
END IF
IF NOT(Fill_Area(xpos-1, ypos+1)) THEN
Real_Fill(0)
ELSE
Real_Fill(color)
END IF
IF NOT(Fill_Area(xpos+1, ypos+1)) THEN
Real_Fill(0)
ELSE
Real_Fill(color)
END IF
END SUB
SUB Draw_Enemy
LOCAL x, y, z
FOR x = 0 TO Xsize-1
FOR y = 0 TO Ysize-1
enemy_board[x][y] = 0
NEXT
NEXT
FOR z = 0 TO Game_Level
INCR en_xpos[z], xoff[z]
IF real_board[en_xpos[z]][en_ypos[z]] <> 0 THEN
IF real_board[en_xpos[z]][en_ypos[z]] = TEMP_LINE THEN
GOSUB Handle_Death
BREAK
ELSE
DECR en_xpos[z], xoff[z]
xoff[z] = -xoff[z]
END IF
END IF
INCR en_ypos[z], yoff[z]
IF real_board[en_xpos[z]][en_ypos[z]] <> 0 THEN
IF real_board[en_xpos[z]][en_ypos[z]] = TEMP_LINE THEN
GOSUB Handle_Death
BREAK
ELSE
DECR en_ypos[z], yoff[z]
yoff[z] = -yoff[z]
END IF
END IF
enemy_board[en_xpos[z]][en_ypos[z]] = ENEMY_COL
enemy_board[en_xpos[z]-1][en_ypos[z]] = ENEMY_COL
enemy_board[en_xpos[z]+1][en_ypos[z]] = ENEMY_COL
enemy_board[en_xpos[z]][en_ypos[z]-1] = ENEMY_COL
enemy_board[en_xpos[z]][en_ypos[z]+1] = ENEMY_COL
NEXT
EXIT SUB
LABEL Handle_Death
OUT("<i><b>You died!</b></i>", "#882222", "#FFFFFF", Xsize/2-15, 50)
DECR Game_Lifes
IF Game_Lifes >= 0 THEN
Game_State = GAME_STP
OUT("Press [r] to retry...", "#000000", "#FFFFFF", Xsize/2-35, 75)
ELSE
Game_State = GAME_END
OUT("<big>GAME OVER!</big>", "#FF0000", "#FFFFFF", Xsize/2-35, 75)
IF Game_Score > VAL(High_Score$) THEN
OUT("Congrats, new high score!", "#000000", "#FFFFFF", Xsize/2-50, 100)
OPEN GETENVIRON$("HOME") & "/.qix.txt" FOR WRITING AS hs
WRITELN STR$(Game_Score) TO hs
CLOSE FILE hs
High_Score$ = STR$(Game_Score)
TEXT(mark5, High_Score$)
END IF
OUT("Start over again (y/n)?", "#000000", "#FFFFFF", Xsize/2-50, 125)
END IF
RETURN
END SUB
FUNCTION Check_Event
LOCAL former
former = real_board[xpos][ypos]
SELECT KEY()
CASE 65362
IF real_board[xpos][ypos-1] < 2 THEN DECR ypos
CASE 65363
IF real_board[xpos+1][ypos] < 2 THEN INCR xpos
CASE 65364
IF real_board[xpos][ypos+1] < 2 THEN INCR ypos
CASE 65361
IF real_board[xpos-1][ypos] < 2 THEN DECR xpos
CASE 114
IF Game_State = GAME_STP THEN
Initialize_Game()
TEXT(mark2, STR$(Game_Lifes))
TEXT(mark4, STR$(Game_Level+1))
TEXT(mark3, STR$(Game_Score))
END IF
CASE 121
IF Game_State = GAME_END THEN
Game_Lifes = 2
Game_Score = 0
Game_Level = 0
Initialize_Game()
TEXT(mark2, STR$(Game_Lifes))
TEXT(mark4, STR$(Game_Level+1))
TEXT(mark3, STR$(Game_Score))
END IF
CASE 110
IF Game_State = GAME_END THEN
OUT("<b>Thanks for playing!</b>", "#228822", "#FFFFFF", Xsize/2-40, 200)
END IF
CASE 65307
QUIT
END SELECT
IF ypos < 2 THEN ypos = 2
IF xpos > Xsize-4 THEN xpos = Xsize-4
IF ypos > Ysize-4 THEN ypos = Ysize-4
IF xpos < 2 THEN xpos = 2
IF Game_State = GAME_RUN THEN
IF former = TEMP_LINE THEN
IF real_board[xpos][ypos] = 1 OR real_board[xpos][ypos] = TEMP_LINE THEN Start_Fill()
END IF
IF real_board[xpos][ypos] = 0 THEN real_board[xpos][ypos] = TEMP_LINE
Draw_Me()
Draw_Enemy()
Draw_Board()
END IF
IF VAL(GRAB$(mark1)) >= THRESHOLD AND Game_State = GAME_RUN THEN
OUT("<i><big>LEVEL COMPLETED!</big></i>", "#208020", "#FFFFFF", Xsize/2-60, 50)
OUT("Press [r] for next level...", "#008000", "#FFFFFF", Xsize/2-55, 75)
Game_State = GAME_STP
INCR Game_Level
INCR Game_Lifes
INCR Game_Score, VAL(GRAB$(mark1))
IF Game_Level = 10 THEN
Game_State = GAME_END
OUT("<big>GAME END</big>", "#22FF22", "#FFFFFF", Xsize/2-35, 75)
IF Game_Score > VAL(High_Score$) THEN
OUT("Congrats, new high score!", "#000000", "#FFFFFF", Xsize/2-50, 100)
OPEN GETENVIRON$("HOME") & "/.qix.txt" FOR WRITING AS hs
WRITELN STR$(Game_Score) TO hs
CLOSE FILE hs
High_Score$ = STR$(Game_Score)
TEXT(mark5, High_Score$)
END IF
OUT("Start over again (y/n)?", "#000000", "#FFFFFF", Xsize/2-50, 125)
END IF
END IF
RETURN TRUE
END FUNCTION
SUB Show_Help
SHOW(Help_Dialog)
END SUB
SUB Close_Help
HIDE(Help_Dialog)
END SUB
INIT
HUGOPTIONS("NOSCALING")
win = WINDOW("Qix", Xsize+120, Ysize+20)
PROPERTY(win, "icon-name", "gtk-select-color")
frame = FRAME(Xsize+10, Ysize+10)
ATTACH(win, frame, 5, 5)
canvas = CANVAS(Xsize, Ysize)
ATTACH(win, canvas, 10, 10)
frame1 = FRAME(95, 40)
TEXT(frame1, " Score ")
ATTACH(win, frame1, Xsize+20, 5)
mark1 = MARK("0%", 85, 30)
ATTACH(win, mark1, Xsize+25, 15)
frame3 = FRAME(95, 40)
TEXT(frame3, " Total ")
ATTACH(win, frame3, Xsize+20, 55)
mark3 = MARK("0", 85, 30)
ATTACH(win, mark3, Xsize+25, 65)
frame5 = FRAME(95, 40)
TEXT(frame5, " High ")
ATTACH(win, frame5, Xsize+20, 105)
mark5 = MARK("0", 85, 30)
ATTACH(win, mark5, Xsize+25, 115)
IF FILEEXISTS(GETENVIRON$("HOME") & "/.qix.txt") THEN
OPEN GETENVIRON$("HOME") & "/.qix.txt" FOR READING AS hs
READLN High_Score$ FROM hs
CLOSE FILE hs
TEXT(mark5, High_Score$)
END IF
frame2 = FRAME(95, 40)
TEXT(frame2, " Lifes ")
ATTACH(win, frame2, Xsize+20, 155)
mark2 = MARK("2", 85, 30)
ATTACH(win, mark2, Xsize+25, 165)
frame4 = FRAME(95, 40)
TEXT(frame4, " Level ")
ATTACH(win, frame4, Xsize+20, 205)
mark4 = MARK("1", 85, 30)
ATTACH(win, mark4, Xsize+25, 215)
help_but = STOCK("gtk-help", 95, 40)
ATTACH(win, help_but, Xsize+20, Ysize-25)
CALLBACK(help_but, Show_Help)
txt$ = "This is a remake of the classic 'Qix' game." & NL$ & NL$ \
& "Goal is to capture at least 75%% of the area." & NL$ & NL$ \
& " Steer your turtle by using the cursor keys, " & NL$ \
& " and use the left CTRL to hold still." & NL$ & NL$ \
& " Can you survive all 10 levels??"
Help_Dialog = MSGDIALOG(txt$, 400, 250, 0, 2)
CALLBACK(Help_Dialog, Close_Help)
Game_Lifes = 2
Initialize_Game()
TIMEOUT(GAME_SPEED, Check_Event)
DISPLAY