?- G_StartLevel := 2, G_MaxLevel := 10, G_Level := G_StartLevel, G_Points := 0, G_Time := 0, G_GameOver := 0, G_Selected := 0, array(table,200,0), array(left,G_MaxLevel + 1, 10), array(right,G_MaxLevel + 1, 0), array(color,G_MaxLevel + 1, 0), array(top, 4*G_MaxLevel + 4, 0), array(bottom, 4 * G_MaxLevel + 4, 0), array(speed,G_MaxLevel + 1, 0), window( _, _, win_func(_), "MuliTetris, Level "+G_Level+", 0 points", 100, 100, 300, 540). menu_new_game(press):- G_Level := G_StartLevel, G_Points := 0, G_Time := 0, G_GameOver := 0, G_Selected := 0, set_text( "MuliTetris, Level "+G_Level+", "+G_Points+" points", _), clean_fig, clean_table, draw_table. menu_help(press):- message("Muli Tetris - Help", "Use the arrows to move the selected figure and the Space bar in order to change the selection.",i). win_func(init):- menu(normal, _, _, menu_new_game(_), "&New Game"), menu(right, _, _, menu_help(_), "&Help"), T is set_timer(_, 0.1, time_func). win_func(paint):- pen(3, rgb(255,0,0)), line(48,48,251,48,251,451,48,451,48,48), pen(0,0), draw_table, draw_all_fig. win_func(key_down(40, Rep)):- % down speed(G_Selected) := 19. win_func(key_down(37, Rep)):- % left shift(left, G_Selected). win_func(key_down(39, Rep)):- % right shift(right, G_Selected). win_func(key_down(32, Rep)):- % space (G_Selected =:= 0 -> bottom_most(G_Selected, 0), (G_Selected>0 -> draw_fig(G_Selected, 1)) else Next := 0, find_next(Next, G_Selected), (Next =:= 0 -> bottom_most(Next, 0) ), (Next>0 -> Old := G_Selected, G_Selected := Next, draw_fig(Old, 1), draw_fig(Next, 1) ) ). win_func(key_down(38, Rep)):- % up G_Selected > 0, roll(G_Selected), not(bottom_collision), not(collision(G_Selected, _)), move(G_Selected). time_func(end):- G_GameOver = 0, G_Time := G_Time+1, (G_Time mod 1000 =:= 0, G_Level G_Level := G_Level+1, set_text( "MuliTetris, Level "+G_Level+", "+G_Points+" points", _) ), Line:=20, End:=0, find_full_line(Line, End), (Line>End-> go_down(Line, End, 1), go_down_fig(Line, End, 1), draw_table, G_Points:=G_Points+1, set_text( "MuliTetris, Level "+G_Level+", "+G_Points+" points", _), beep ), (G_Selected =:= 0 -> bottom_most(G_Selected, 0) ), for(F, 1, G_Level), falling(F, speed(F)), (collision(F, Who) -> Speed := speed(Who), speed(Who) := speed(F), speed(F) := Speed else (bottom_collision -> (F =:= G_Selected -> G_Selected := 0 ), lay_down(F), fill_table(F), move(F), left(F) := 10 else move(F) )), fail. time_func(end):- G_GameOver = 0, F is random(G_Level)+1, left(F)=:=10, create(F), not(collision(F, _)), (bottom_collision-> G_GameOver := 1, message("Game Over", "Your result is "+ G_Points, i) else jump_in(0, F) ). draw_table:- for(Y,0,19), for(X,0,9), draw_sqr(X,Y), fail. draw_table. clean_table:- for(Y,0,19), for(X,0,9), table(10*Y+X):=0, fail. clean_table. clean_fig:- for(F, 1, G_MaxLevel), left(F) := 10, fail. clean_fig. draw_sqr(X,Y):- S is table(10*Y+X), color(S,Ex), brush(Ex), rect(50+20*X,50+20*Y,71+20*X,71+20*Y). draw_all_fig:- for(F, 1, G_Level), left(F) < 10, draw_fig(F, 1), fail. draw_all_fig. draw_fig(F, Flag):- (Flag = 1 -> C := color(F) else C := 0 ), (F =:= G_Selected, Flag = 1 -> C := C + 7 ), color(C, Ex), brush(Ex), for(R, left(F), right(F)), rect(50+20*R, 50+top(4*F+R-left(F)), 71+20*R, 51+bottom(4*F+R-left(F))), fail. draw_fig(F, Flag). falling(F, Speed):- left(0) := left(F), right(0) := right(F), for(I, 0, 3), top(I) := top(4*F+I) + Speed, bottom(I) := bottom(4*F+I) + Speed, fail. falling(F, Speed). jump_in(From, To):- left(To) := left(From), right(To) := right(From), for(R, 0, 3), top(4*To+R) := top(4 * From + R), bottom(4*To+R) := bottom(4 * From + R), fail. jump_in(From, To). move(F):- draw_fig(F, 0), jump_in(0, F), draw_fig(F, 1). create(F):- color(F) := random(7)+1, speed(F) := 1 + random(G_Level-G_MaxLevel+19), Shape is color(F), % random(7)+1 shape(Shape). collision(Old, Who):- for(R, left(0), right(0)), for(Who, 1, G_Level), Who =\= Old, left(Who) =\= 10, R >= left(Who), R =< right(Who), intersect(top(R-left(0)), bottom(R - left(0)), top(4*Who+R-left(Who)), bottom(4*Who+R-left(Who))). intersect(A1, B1, A2, B2):- A2 =< A1, A1 =< B2; %; = OR A1 =< A2, A2 =< B1. bottom_most(F, Height):- for(I, 1, G_Level), left(I)<10, for(R, left(I), right(I)), A is bottom(4*I + R-left(I)), A > Height, Height := A, F := I, fail. bottom_most(F, Height). bottom_collision:- left(0)<0; right(0)>9. bottom_collision:- Top := 10000, calc_top(Top, 0), Top<0. bottom_collision:- for(R, left(0), right(0)), bottom(R-left(0)) > 400. bottom_collision:- for(R, left(0), right(0)), Y1 is top(R-left(0)) // 20, Y2 is bottom(R-left(0)) // 20, for(I, Y1, Y2 - true_value(top(0) mod 20 =:= 0)), table(10*I + R) > 0. lay_down(F):- for(R, left(F), right(F)), Y1 is (top(4*F+R-left(F))+19) // 20, Y2 is (bottom(4*F+R-left(F))+19) // 20, top(R-left(F)) := Y1 * 20, bottom(R-left(F)) := Y2 * 20, fail. lay_down(F). fill_table(F):- for(R, left(F), right(F)), Y1 is (top(4*F+R-left(F))+19) // 20, Y2 is (bottom(4*F+R-left(F))+19) // 20, for(I, Y1, Y2-1), table(10*I+R) := color(F), fail. fill_table(F). shift(Direction, F):- F > 0, jump_in(F, 0), (Direction = left -> left(0) := left(F) - 1, right(0) := right(F) - 1 else left(0) := left(F) + 1, right(0) := right(F) + 1 ), (bottom_collision-> More is 20 - top(0) mod 20, More > 0, More < 2*speed(F), lay_down(0), not(bottom_collision), not(collision(F, _)), move(F) else (collision(F, Who) -> shift(Direction, Who) else move(F) )). calc_bottom(Res, F) :- for(R, left(F), right(F)), S is bottom(4*F+R-left(F)), Res < S, Res := S, fail. calc_bottom(Res, F). calc_top(Res, F) :- for(R, left(F), right(F)), S is top(4*F+R-left(F)), Res > S, Res := S, fail. calc_top(Res, F). before(F1, Bottom1, F2, Bottom2) :- Bottom1 < Bottom2; Bottom1 = Bottom2, F1 < F2. find_next(Next, Fig) :- Bottom1 := 0, calc_bottom(Bottom1, Fig), BestBottom := 0, for(F, 1, G_Level), left(F)<10, Bottom2 := 0, calc_bottom(Bottom2, F), before(F, Bottom2, Fig, Bottom1), before(Next, BestBottom, F, Bottom2), Next := F, BestBottom := Bottom2, fail. find_next(Next, Fig). roll(F):- Top := 10000, calc_top(Top, F), Bottom := 0, calc_bottom(Bottom, F), X is right(F) - left(F) + 1, Y is (Bottom - Top) // 20, (Y = 1 -> left(0) := left(F) + 1, right(0) := left(0), top(0) := Top - 30, bottom(0) := Bottom + 30 else (X = 1 -> left(0) := left(F) - 1, right(0) := left(0) + 3, top(0) := Top + 30, top(1) := top(0), top(2) := top(0), top(3) := top(0), bottom(0) := Bottom - 30, bottom(1) := bottom(0), bottom(2) := bottom(0), bottom(3) := bottom(0) else ( X = 2, Y = 2 -> fail else left(0) := left(F), (X = 2 -> Bottom2 := Bottom-10, right(0) := left(0) + 2 else Bottom2 := Bottom+10, right(0) := left(0) + 1 ), make_rows(F, Top, Bottom2) ))). make_rows(F, Top, Bottom2):- for(R, left(0), right(0)), make_row(F, Top, Bottom2, R), fail. make_rows(F, Top, Bottom2). make_row(F, Top, Bottom2, R):- Row is R - left(0), Level is Top + 20*Row + 10, calc_start(F, Level, Start), bottom(Row) := Bottom2 - 20*Start, calc_end(F, Level, Start), top(Row) := Bottom2 - 20*Start. calc_start(F, Level, Start) :- (top(4*F) < Level, Level < bottom(4*F) -> Start := 0 else (top(4*F+1) < Level, Level < bottom(4*F+1) -> Start := 1 else Start := 2 )). calc_end(F, Level, Start) :- (left(F)+Start+1>right(F); top(4*F+Start+1) >= Level; Level >= bottom(4*F+Start+1) -> Start := Start+1 else (left(F)+Start+2>right(F); top(4*F+Start+2) >= Level; Level >= bottom(4*F+Start+2) -> Start := Start+2 else Start := Start+3 )). find_full_line(Line, End):- repeat, Line:=Line-1, not(has_hole(Line), Line>End), !. has_hole(Line):- for(X, 0, 9), table(10*Line+X)=:=0. go_down(Start, End, Shift):- for(I, Start, End, -1), copy_line(I, Shift), fail. go_down(Start, End, Shift). copy_line(Line, Shift):- for(X, 0, 9), table(10*Line+X):=table(10*(Line-Shift)+X), fail. copy_line(Line, Shift). go_down_fig(Start, End, Shift):- for(F, 1, G_Level), left(F)<10, Bottom := 0, calc_bottom(Bottom, F), Bottom<20*Start, Bottom>20*End, falling(F, 20*Shift), jump_in(0, F), fail. go_down_fig(Start, End, Shift). shape(1):- left(0):= random(7), right(0):= left(0)+3, top(0) := 20, top(1) := 20, top(2) := 20, top(3) := 20, bottom(0) := 40, bottom(1) := 40, bottom(2) := 40, bottom(3) := 40. shape(2):- left(0):= random(8), right(0):= left(0)+2, top(0) := 20, top(1) := 0, top(2) := 20, bottom(0) := 40, bottom(1) := 40, bottom(2) := 40. shape(3):- left(0):= random(8), right(0):= left(0)+2, top(0) := 0, top(1) := 20, top(2) := 20, bottom(0) := 40, bottom(1) := 40, bottom(2) := 40. shape(4):- left(0):= random(8), right(0):= left(0)+2, top(0) := 20, top(1) := 20, top(2) := 0, bottom(0) := 40, bottom(1) := 40, bottom(2) := 40. shape(5):- left(0):= random(8), right(0):= left(0)+2, top(0) := 0, top(1) := 0, top(2) := 20, bottom(0) := 20, bottom(1) := 40, bottom(2) := 40. shape(6):- left(0):= random(8), right(0):= left(0)+2, top(0) := 20, top(1) := 0, top(2) := 0, bottom(0) := 40, bottom(1) := 40, bottom(2) := 20. shape(7):- left(0):= random(9), right(0):= left(0)+1, top(0) := 0, top(1) := 0, bottom(0) := 40, bottom(1) := 40. color(0, system_color(window)). color(1, rgb(200,0,0)). color(2, rgb(0,200,0)). color(3, rgb(0,0,200)). color(4, rgb(200,200,0)). color(5, rgb(200,0,200)). color(6, rgb(0,200,200)). color(7, rgb(0,100,0)). color(8, rgb(255,100,100)). color(9, rgb(100,255,100)). color(10, rgb(100,100,255)). color(11, rgb(255,255,100)). color(12, rgb(255,100,255)). color(13, rgb(100,255,255)). color(14, rgb(100,150,100)).