% Project PKB kelompok 1
% Gunadarma 3IA22
?-G_HighScore := 0, G_LastShipWay := 0,
G_player_color:=brush(rgb(0,0,128)), G_enemy_color:=brush(rgb(0,128,255)), G_Red:=brush(rgb(255,100,100)),
window( _, _, win_func(_), "Star Wars", 100, 100, 490, 410).
first_sleeping_paint.
width(480) :- !.
height(380) :- !.
%dead or alive?
dead.
%ship data:
ship_half_width(20) :- !.
ship_height(25) :- !.
ship_minship(70) :- !.
%enemies:
enemy_ships([]).
enemy_bombs([]).
%speed:
speed(10) :- !.
%G_EnemySpeed
player_bomb_speed(15) :- !.
%player:
player_bombs([]).
%way of the last ship:
%G_LastShipWay
%difficulty:
%G_Difficulty
%difficulty(1000).
die(_) :- !, assert(first_sleepint_paint), assert(dead).
start_game(P, S, PTS) :- !,
retract(dead),
retract(enemy_ships(_)), assert(enemy_ships([])),
retract(enemy_bombs(_)), assert(enemy_bombs([])),
width(W), height(H), X is W >> 1, Y is H - 1,
G_D := 0,
G_X := X,
G_Y := Y,
%retract(player_ship(_,_,_)), assert(player_ship(null, X, Y)),
retract(player_bombs(_)), assert(player_bombs([])),
(paused -> retract(paused)),
G_Difficulty := P,
G_EnemySpeed := S,
G_DirectionTimer := 0,
G_PTS := PTS,
G_Score := 0,
update_window(_).
is_in_ship(X, Y, PX, PY) :- !,
ship_left(X) =< PX,
ship_right(X) >= PX,
ship_up(Y) =< PY,
ship_down(Y) >= PY.
crash(X1, Y1, X2, Y2) :- !,
TX1 is ship_left(X1),
TX2 is ship_right(X1),
TY1 is ship_up(Y1),
TY2 is ship_down(Y1),
do_crash_check(TX1, TX2, TY1, TY2, X2, Y2).
do_crash_check(TX1, TX2, TY1, TY2, X2, Y2) :- is_in_ship(X2, Y2, TX1, TY1), !.
do_crash_check(TX1, TX2, TY1, TY2, X2, Y2) :- is_in_ship(X2, Y2, TX1, TY2), !.
do_crash_check(TX1, TX2, TY1, TY2, X2, Y2) :- is_in_ship(X2, Y2, TX2, TY1), !.
do_crash_check(TX1, TX2, TY1, TY2, X2, Y2) :- is_in_ship(X2, Y2, TX2, TY2), !.
%border coordiates inside a ship:
R is ship_up(int Y) :- !, ship_height(SH), R0 is Y - SH, R is R0 + 1.
R is ship_down(int Y) :- !, R is Y.
R is ship_left(int X) :- !, ship_half_width(SHW), R is X - SHW.
R is ship_right(int X) :- !, ship_half_width(SHW), R is X + SHW.
add_enemy(_) :- X is G_LastShipWay, ship_minship(Y), X > Y,
R0 is random(1000), R1 is G_Difficulty, R2 is R1 >> 1, R0 < R2, !,
width(W), ship_half_width(HW), W1 is W - HW - HW, XNEW is random(W1) + HW,
enemy_ships(L), random_left_right(D), ship_height(SHH), L1 is [ship(D, XNEW, SHH)|L],
retract(enemy_ships(_)), assert(enemy_ships(L1)),
G_LastShipWay := 0.
add_enemy(_) :- !.
random_left_right(X) :- Y is random(1000), Y < 500, !, X is left.
random_left_right(right) :- !.
fire_enemy(X, Y) :- R0 is random(1000), R1 is G_Difficulty, R2 is R1 >> 2, R0 < R2, !,
enemy_bombs(L), random_speed(S), L1 is [bomb(S, X, Y)|L],
retract(enemy_bombs(_)), assert(enemy_bombs(L1)).
fire_enemy(X, Y) :- !.
random_speed(S) :- !, S0 is G_EnemySpeed, S1 is S0 / 4, S2 is S0 * 1.5, S3 is S1 * 1000, S4 is S2 * 1000,
S5 is S4 - S3, INTS5 is integer(S5), R0 is random(INTS5) + S3, S is R0 / 1000.
fire_player(_) :- firing, !, retract(firing), player_bombs(L), X is G_X, Y is G_Y, ship_height(SH), Y1 is Y - SH - 7,
(autofire -> AutoFire := 1 else AutoFire := 0), L1 is [bomb(AutoFire, X, Y1)|L],
retract(player_bombs(_)), assert(player_bombs(L1)).
fire_player(_) :- !.
update_positions(_) :- !, update_enemies(_), update_bombs(_), update_player_bombs(_), update_player(_).
% {{ UPDATE_ENEMIES:
update_enemies(_) :- !, enemy_ships(L), update_enemy(L, R), retract(enemy_ships(_)), assert(enemy_ships(R)).
update_enemy([], []) :- !.
update_enemy([ship(D, X, Y)|T], R) :- height(H), S is G_EnemySpeed, Y1 is ship_down(Y + S), Y1 > H, !, update_enemy(T, R).
update_enemy([ship(D, X, Y)|T], [ship(D, RX, RY)|R]) :- S is G_EnemySpeed, preserve_direction(D, S, X, RX), !, RY is Y + S, update_enemy(T, R).
update_enemy([ship(D, X, Y)|T], [ship(RD, X, RY)|R]) :- !, S is G_EnemySpeed, RY is Y + S, opposite(D, RD), update_enemy(T, R).
preserve_direction(left, S, X, RX) :- !, RX is X - S, ship_left(RX) >= 0.
preserve_direction(right, S, X, RX) :- !, RX is X + S, width(W), ship_right(RX) < W.
opposite(left, right) :- !.
opposite(right, left) :- !.
% }}
%update enemy bombs:
update_bombs(_) :- !, enemy_bombs(L), update_bomb(L, R), retract(enemy_bombs(_)), assert(enemy_bombs(R)).
update_bomb([], []) :- !.
update_bomb([bomb(S, X, Y)|T], R) :- height(H), Y1 is Y + S, Y1 > H, !, update_bomb(T, R).
update_bomb([bomb(S, X, Y)|T], [bomb(S, X, RY)|R]) :- !, RY is Y + S, update_bomb(T, R).
%update player bombs:
update_player_bombs(_) :- !, player_bombs(L), update_player_bomb(L, R), retract(player_bombs(_)), assert(player_bombs(R)).
update_player_bomb([], []) :- !.
update_player_bomb([bomb(_, X, Y)|T], R) :- player_bomb_speed(S), Y1 is Y - S, Y1 < 0, !, update_player_bomb(T, R).
update_player_bomb([bomb(AutoFire, X, Y)|T], [bomb(AutoFire, X, RY)|R]) :- !, player_bomb_speed(S), RY is Y - S, update_player_bomb(T, R).
%update player:
update_player(_) :- G_DirectionTimer > 0, !, D is G_D, X is G_X, Y is G_Y, speed(S), update_player_impl(S, D, X, Y, RX, RY), G_X := RX, G_Y := RY.
update_player(_) :- !.
update_player_impl(S, 1, X, Y, X, RY) :- Y0 is Y - S, ship_up(Y0) < 0, !, ship_height(RY).
update_player_impl(S, 1, X, Y, X, RY) :- !, RY is Y - S.
update_player_impl(S, 4, X, Y, X, RY) :- Y1 is Y + S, height(H), Y1 >= H, !, RY is H - 1.
update_player_impl(S, 4, X, Y, X, RY) :- !, RY is Y + S.
update_player_impl(S, 2, X, Y, RX, Y) :- X0 is X - S, ship_left(X0) < 0, !, ship_half_width(RX).
update_player_impl(S, 2, X, Y, RX, Y) :- !, RX is X - S.
update_player_impl(S, 3, X, Y, RX, Y) :- X0 is X + S, width(W), ship_right(X0) > W, !, ship_half_width(HW), RX is W - HW.
update_player_impl(S, 3, X, Y, RX, Y) :- !, RX is X + S.
update_player_impl(S, D, X, Y, X, Y) :- !.
win_func(init) :- !,
pen(0, rgb(0,0,0)),
X is 1/30,
G_Timer := set_timer(_, X, do_timer),
fail.
win_func(paint):- !,
width(W), height(H),
brush(rgb(10, 10, 10)),
paint_score(_),
not(dead),
brush(G_player_color),
paint_player(_),
draw_player_bombs(_),
brush(G_enemy_color),
draw_enemies(_),
draw_enemy_bombs(_),
fail.
win_func(close) :- !,
kill_timer(_, G_Timer),
fail.
win_func(key_down(Char, Repetition)) :- dead, !, key_start_game(Char), fail.
win_func(key_down(Char, Repetition)) :- !, key_pressed(Char), fail.
paint_player(_) :- !,
X is G_X, Y is G_Y,
X1 is ship_left(X),
X2 is ship_right(X),
YY is ship_up(Y),
fill_polygon(X1,Y, X2,Y, X,YY).
paint_score(_) :- dead, !,
text_out(20, 20, "1 - LEVEL ANAK TK KECIL"),
text_out(20, 50, "2 - LEVEL ANAK TK BESAR"),
text_out(20, 80, "3 - LEVEL ANAK SD"),
text_out(20, 110, "4 - LEVEL ANAK SMP"),
text_out(20, 140, "5 - DEWA BOS!!!"),
text_out(20, 170, "F1 - Help"),
text_out(20, 200, "HighScore"),
text_out(99, 200, ":"),
text_out(114, 200, print(G_HighScore)).
paint_score(_) :- !,
text_out(20,20,"HighScore"),
text_out(99,20,":"),
text_out(114,20,print(G_HighScore)),
text_out(20,50,"Score"),
text_out(99,50,":"),
text_out(114,50,print(G_Score)).
draw_enemies(_) :- !, enemy_ships(L), d_e(L).
d_e([]) :- !.
d_e([ship(_, X, Y)|T]) :- !,
ship_half_width(HW), ship_height(SH),
X1 is ship_left(X),
X2 is ship_right(X),
YY is ship_up(Y),
fill_polygon(X1,YY, X2,YY, X, Y), d_e(T).
draw_enemy_bombs(_) :- !, enemy_bombs(L), d_eb(L).
d_eb([]) :- !.
d_eb([bomb(_, X, Y)|T]) :- !,
Y1 is Y - 7,
XX is round(X),
YY is round(Y),
YY1 is round(Y1),
fill_polygon(XX - 1,YY, XX + 1,YY, XX + 1, YY1, XX - 1, YY1), d_eb(T).
draw_player_bombs(_) :- !, player_bombs(L), d_pb(L).
d_pb([]) :- !.
d_pb([bomb(AutoFire, X, Y)|T]):- !,
Y1 is Y + 7,
XX is round(X),
YY is round(Y),
YY1 is round(Y1),
(Condition is f ->
(AutoFire is 1 -> brush(G_Red) else brush(G_player_color))
),
fill_polygon(XX - 1,YY, XX + 1,YY, XX + 1, YY1, XX - 1, YY1), d_pb(T).
key_pressed(87) :- !, set_moving(1). % W
key_pressed(38) :- !, set_moving(1). % up
key_pressed(65) :- !, set_moving(2). % A
key_pressed(37) :- !, set_moving(2). % <-
key_pressed(68) :- !, set_moving(3). % D
key_pressed(39) :- !, set_moving(3). % ->
key_pressed(83) :- !, set_moving(4). % S
key_pressed(40) :- !, set_moving(4). % down
key_pressed(80) :- !, set_pause(_). % P
key_pressed(81) :- !, assert_autofire(_). % Q
key_pressed(75) :- !, not(autofire), beep, assert(firing). % K
key_pressed(32) :- !, not(autofire), beep,assert(firing). % space
key_pressed(190) :- !, die(_), update_window(_). % dot
key_pressed(X) :- !, G_DirectionTimer := 0, G_D := 0.
assert_autofire(_) :- autofire, !, retract(autofire).
assert_autofire(_) :- !, assert(autofire).
set_pause(_) :- paused, !, retract(paused).
set_pause(_) :- !, assert(paused).
key_start_game(49) :- !, start_game(100, 5, 0). % 1
key_start_game(50) :- !, start_game(150, 7, 1). % 2
key_start_game(51) :- !, start_game(250, 10, 1). % 3
key_start_game(52) :- !, start_game(350, 11, 2). % 4
key_start_game(53) :- !, start_game(500, 17, 4). % 5
key_start_game(83) :- !, start_game(1000, 2, 10). % S
key_start_game(112) :- !, message("Help","Spasi buat nembak\nArah buat gerak\nP - pause\nQ - Senjata rahasia\npoint - quick dead",i). % S
key_start_game(X) :- !.
set_moving(D) :- !, G_DirectionTimer := 1, G_D := D.
check_collisions(_) :- !, enemy_ships(EShips), enemy_bombs(EBombs), check_es(EShips, NewShips), check_eb(EBombs), retract(enemy_ships(_)), assert(enemy_ships(NewShips)).
check_es([],[]) :- !.
check_es([ship(D, X, Y)|T], []) :- X1 is G_X, Y1 is G_Y, crash(X, Y, X1, Y1), !, die(_).
check_es([ship(D, X, Y)|T], [ship(D, X, Y)|R]) :- survive_enemy(X, Y), !, check_es(T, R).
check_es([ship(D, X, Y)|T], R) :- !, (G_AutoFired is 0 -> G_Score := G_Score + G_PTS else G_Score := G_Score - G_PTS),
(G_HighScore < G_Score -> G_HighScore := G_Score), G_Difficulty := G_Difficulty + 2, check_es(T, R).
survive_enemy(X, Y) :- !, player_bombs(Bombs), s_e(X, Y, Bombs).
s_e(_, _, []) :- !.
s_e(X, Y, [bomb(AutoFire, BX, BY)|T]) :- is_in_ship(X, Y, BX, BY), !, G_AutoFired := AutoFire, fail.
s_e(X, Y, [bomb(_, _, BY)|T]) :- !, s_e(X, Y, T).
check_eb([]) :- !.
check_eb([bomb(_, BX, BY)|T]) :- X1 is G_X, Y1 is G_Y, is_in_ship(X1, Y1, BX, BY), !, die(_).
check_eb([bomb(_, BX, BY)|T]) :- !, check_eb(T).
fire_enemies(_) :- !, enemy_ships(L), f_e(L).
f_e([]) :- !.
f_e([ship(_, X, Y)|T]) :- !, fire_enemy(X, Y), f_e(T).
do_timer(end) :- not(dead), !,
(paused -> text_out(200,200,"Paused"), fail),
(autofire -> assert(firing)),
fire_player(_),
fire_enemies(_),
update_positions(_),
check_collisions(_),
S is G_EnemySpeed,
G_LastShipWay := G_LastShipWay + S,
add_enemy(_),
update_window(_),
fail.
do_timer(end) :- !,
paint_sleeping(_), fail.
paint_sleeping(_) :- first_sleeping_paint, !, retract(first_sleepint_paint), update_window(_).
paint_sleeping(_) :- !.