?- G_Zoom:=2.5, G_PosX:= -100.0, G_PosY:= -60.0, G_PlayWith:=0, G_Action:=no, G_MaxObj:=128, array(cc_x,G_MaxObj,0.0), array(cc_y,G_MaxObj,0.0), array(cc_t,G_MaxObj,0), array(cc_h,G_MaxObj,100), array(attack,G_MaxObj,1), array(status,G_MaxObj,8), % 0-stand by , 1-fire stand by , 2-attack, 3-fire, 4-move, 6-dead array(tar_x,G_MaxObj,0.0), array(tar_y,G_MaxObj,0.0), array(born,G_MaxObj,0), G_CC:=2, cc_x(1):=random(2000)-1000, cc_y(1):=random(2000)-1000, cc_t(1):=1, pen(0,0), window(G_SelWin,_,sel_func(_),"Selected",810,10,200,600), window(G_MainWin,_,main_func(_),"War Craft",10,10,800,600). selection(). sel_func(paint):- selection(|List), draw_list(List,0). sel_func(close):- close(G_MainWin), fail. menu_move(press):- G_Action:= move, set_text("War Craft (show me where to move)", G_MainWin). menu_attack(press):- G_Action:= attack, set_text("War Craft (show me who to attack)", G_MainWin). menu_stop(press):- action(stop). menu_build(press):- action(build). menu_play_with(init):- menu(checked,_,_,play_with_red(_),"The &Red"), menu(normal,_,_,play_with_blue(_),"The &Blue"), menu(normal,_,_,play_with_both(_),"&Both"). play_with_red(press):- play_with(0). play_with_blue(press):- play_with(1). play_with_both(press):- play_with(2). play_with(PlayWith):- modify_menu(G_Menu,G_PlayWith+1,normal,_), G_PlayWith :=PlayWith, modify_menu(G_Menu,PlayWith+1,checked,_). menu_help(press):- message("War Craft - Help", "You are in an infinite forest. You are involved in one epic battle. In order to move use the arrows. Zoom in and out by the mouse wheel (in combination with the left mouse button). Select objects by the mouse.",i). main_func(init):- menu(normal, _, _, menu_move(_), "&Move"), menu(normal, _, _, menu_attack(_), "&Attack"), menu(normal, _, _, menu_stop(_), "&Stop"), menu(normal, _, _, menu_build(_), "&Build"), menu(pop_up, G_Menu, _, menu_play_with(_),"&Play with"), menu(right, _, _, menu_help(_), "&Help"), _ is set_timer(_, 0.2, time_func). main_func(paint):- G_Zoom>0.005, paint_rect(A,B,C,D), X1 is floor((G_PosX+A/G_Zoom - 50)/100), X2 is floor((G_PosX+C/G_Zoom)/100), Y1 is floor((G_PosY+B/G_Zoom - 50)/100), Y2 is floor((G_PosY+D/G_Zoom)/100), for(J,Y1,Y2), for(I,X1,X2), X is floor((I*100-G_PosX)*G_Zoom), Y is floor((J*100-G_PosY)*G_Zoom), Size is floor(175*G_Zoom), paint_rect(X,Y,X+Size,Y+Size), my_start_random_from(I, J), (is_it_wet-> Elx is 1+ceiling(100*G_Zoom), Ely is 1+ceiling(100*G_Zoom), Random1 is 1+ceiling((10+random(90))*G_Zoom), %brush(rgb(255,0,0)), rect(X, Y, X+Elx, Y+Ely), brush(rgb(0,255,255)), my_start_random_from(I, J-1), (is_it_wet-> my_start_random_from(I, J+1), (is_it_wet-> rect(X, Y, X+Elx, Y+Ely) else my_start_random_from(I-1, J), Left is (is_it_wet-> 1 else 0), my_start_random_from(I+1, J), Right is (is_it_wet-> 1 else 0), (Left+Right=:=2 -> rect(X, Y, X+Elx, Y+Ely) else (Left+Right=:=0 -> draw_chord(X, Y-Random1, X+Elx, Y+Random1, X, Y, X+Elx, Y) else (Left=:=1 -> draw_pie(X-Elx, Y-Ely, X+Elx, Y+Ely, X, Y+Ely, X+Elx, Y) else draw_pie(X, Y-Ely, X+2*Elx, Y+Ely, X, Y, X+Elx, Y+Ely) ))) ) else my_start_random_from(I-1, J), Left is (is_it_wet-> 1 else 0), my_start_random_from(I+1, J), Right is (is_it_wet-> 1 else 0), my_start_random_from(I, J+1), Down is (is_it_wet-> 1 else 0), (Left+Right=:=2 -> rect(X, Y, X+Elx, Y+Ely) else (Left+Right=:=0 -> (Down=:=1 -> draw_chord(X, Y+Ely-Random1, X+Elx, Y+Ely+Random1, X+Elx, Y+Ely, X, Y+Ely) else fail, ellipse(X, Y, X+Elx, Y+Ely) ) else (Left=:=1 -> (Down=:=1 -> draw_pie(X-Elx, Y, X+Elx, Y+2*Ely, X+Elx, Y+Ely, X, Y) else draw_chord(X-Random1, Y, X+Random1, Y+Ely, X, Y+Ely, X, Y) ) else (Down=:=1 -> draw_pie(X, Y, X+2*Elx, Y+2*Ely, X+Elx, Y, X, Y+Ely) else draw_chord(X+Elx-Random1, Y, X+Elx+Random1, Y+Ely, X+Elx, Y, X+Elx, Y+Ely) ) ))) ), fail ), G_Zoom>0.05, for(_, 0,10*random(2)), Elx is X+floor(random(100)*G_Zoom), Ely is Y+floor(random(100)*G_Zoom), Elr is floor((5 +random(10))*G_Zoom), brush(rgb(0,random(256),0)), fill_polygon(Elx+Elr, Ely, Elx, Ely+3*Elr, Elx+2*Elr, Ely+3*Elr), fail. main_func(paint):- G_Zoom>0.05, for(I,0,G_CC-1), draw_object(I), fail. main_func(key_down(77, Rep)):- menu_move(press). main_func(key_down(65, Rep)):- menu_attack(press). main_func(key_down(66, Rep)):- menu_build(press). main_func(key_down(83, Rep)):- menu_stop(press). main_func(key_down(Char, Rep)):- Xold:=G_PosX, Yold:=G_PosY, (Char=37; Char=36; Char=35-> % left G_PosX:= G_PosX - G_Xsize*0.02*Rep/G_Zoom ), (Char=39; Char=34; Char=33-> % right G_PosX:= G_PosX + G_Xsize*0.02*Rep/G_Zoom ), (Char=38; Char=36; Char=33-> % up G_PosY:= G_PosY - G_Ysize*0.02*Rep/G_Zoom ), (Char=40; Char=34; Char=35-> % down G_PosY:= G_PosY + G_Ysize*0.02*Rep/G_Zoom ), move(Xold, Yold). main_func(size(X,Y)):- G_Xsize:=X, G_Ysize:=Y. main_func(mouse_wheel(Delta, X, Y)):- (message_flags(left)-> client(G_MainWin,A,B,_,_), zoom(0-Delta, X-A, Y-B) else Yold:=G_PosY, G_PosY:= G_PosY - 3*G_Ysize*0.02*Delta/G_Zoom, move(G_PosX, Yold) ). main_func(mouse_click(X,Y)):- G_ClickX:=G_PosX+X/G_Zoom, G_ClickY:=G_PosY+Y/G_Zoom. main_func(mouse_click_up(X,Y)):- A:=G_PosX+X/G_Zoom, B:=G_PosY+Y/G_Zoom, (G_Action \= no-> set_text("War Craft", G_MainWin), action(G_Action, A, B) else ((A-G_ClickX)**2+(B-G_ClickY)**2 > 9*G_Zoom**2 -> MinX is min(G_ClickX,A), MaxX is max(G_ClickX,A), MinY is min(G_ClickY,B), MaxY is max(G_ClickY,B), findall(Obj,find_in_rect(MinX,MinY,MaxX,MaxY,Obj),List), make_new_sel(List) else (find_object(A,B,Obj,0) -> make_new_sel([Obj]) else make_new_sel([]) ))), update_window(G_SelWin). main_func(close):- close(G_SelWin), fail. my_start_random_from(I, J):- Abs is abs(I) + abs(J), start_random_from(true_value(I>0)+ 2*true_value(J>0) + 4* ((1+Abs)*Abs//2+abs(I))). is_it_wet:- random(100)<30. make_new_sel(List):- selection(|OldList), set(selection(|List)), union(OldList, List, Union), draw_all(Union). draw_all([]). draw_all([H|T]):- draw_object(H), draw_all(T). union([], B, B). union([H|T], B, [H|Res]):- union(T, B, Res). move(Xold, Yold):- scroll_window(G_MainWin, ceiling(Xold*G_Zoom)-ceiling(G_PosX*G_Zoom), ceiling(Yold*G_Zoom)-ceiling(G_PosY*G_Zoom), 1). zoom(Delta, X, Y):- G_Zoom:=G_Zoom*0.9**Delta, G_PosX:= G_PosX - X* (1 - 0.9**Delta)/G_Zoom, G_PosY:= G_PosY - Y* (1 - 0.9**Delta)/G_Zoom, update_window(G_MainWin). action(move, A, B):- G_Action:=no, selection(|List), element(P, List), cc_t(P) >= 100, cc_t(P) mod 4 =\= 1-G_PlayWith, tar_x(P):=A, tar_y(P):=B, status(P):=4, fail. action(attack, A, B):- G_Action:=no, find_object(A,B,Obj,0), selection(|List), element(P, List), cc_t(P) >= 100, cc_t(P) mod 4 =\= 1-G_PlayWith, attack(P):=Obj, status(P):=2, fail. action(stop):- selection(|List), element(P, List), cc_t(P) >= 100, cc_t(P) mod 4 =\= 1-G_PlayWith, status(P):=status(P) mod 2, fail. action(build):- selection(|List), element(P, List), cc_t(P) >= 100, cc_t(P) mod 4 =\= 1-G_PlayWith, build(P), draw_object(P), fail. time_func(end):- (G_Action \= no -> cursor(c) ), update_window(G_SelWin), for(P,0,G_CC-1), (status(P) =:= 4 -> move_object(P,tar_x(P),tar_y(P),2) else ( status(P) mod 2 =:= 1 -> move_shell(P,cc_x(attack(P)),cc_y(attack(P)),4) else ( status(P) =:= 2 -> ( cc_t(attack(P)) mod 4 =:= 2 -> status(P):=0 else ( (cc_x(P)-cc_x(attack(P)))**2 + (cc_y(P)-cc_y(attack(P)))**2 > 10000 -> move_object(P,cc_x(attack(P)),cc_y(attack(P)),3) else status(P):=3, tar_x(P):=cc_x(P), tar_y(P):=cc_y(P) )) else ( status(P) =:= 0 -> (find_enemy(P,near,Enemy) -> status(P):=1, attack(P):=Enemy, tar_x(P):=cc_x(P), tar_y(P):=cc_y(P) ) else ( status(P) =:= 8 -> born(P):=born(P)+5, (born(P)>100 -> born(P):=0, make_soldier(P) ) ))))), fail. make_soldier(P):- find_place(A, B, 0, 20, P, 5), find_new_object(New), !, cc_x(New):=A, cc_y(New):=B, cc_t(New):=cc_t(P)+100, cc_h(New):=100, (cc_t(New) mod 4 =:= G_PlayWith-> status(New):=0 else (random(100) < 80, find_enemy(P,far,Enemy) -> status(New):=2, attack(New):=Enemy else status(New):=4, tar_x(New):=cc_x(New)+(200+random(100))*(1-2*random(2)), tar_y(New):=cc_y(New)+(200+random(100))*(1-2*random(2)) )), draw_object(New). move_object(P,X,Y,Speed):- Length is sqrt( (cc_x(P)-X)**2 + (cc_y(P)-Y)**2 ), (Length < Speed -> A is X-cc_x(P), B is Y-cc_y(P) else A is Speed*(X-cc_x(P))/Length, B is Speed*(Y-cc_y(P))/Length ), find_place(X2, Y2, A, B, P, 5), clean_object(P), cc_x(P):=X2, cc_y(P):=Y2, (Length < Speed -> (cc_t(P) mod 4 =:= G_PlayWith-> status(P):=0 else build(P) ) ), draw_object(P). build(P):- (find_another_object(cc_x(P), cc_y(P), P, 12)-> status(P):=0 else status(P):=8, cc_t(P):=cc_t(P)-100 ). move_shell(P,X,Y,Speed):- draw_shell(P,1), Length is sqrt( (tar_x(P)-X)**2 + (tar_y(P)-Y)**2 ), (Length < Speed -> tar_x(P):=X, tar_y(P):=Y, status(P):=status(P)-1, kill_object(P, 5) else tar_x(P):=tar_x(P)+Speed*(X-tar_x(P))/Length, tar_y(P):=tar_y(P)+Speed*(Y-tar_y(P))/Length ), draw_shell(P,0). kill_object(P,Damage):- P1 is attack(P), cc_h(P1):=cc_h(P1)-Damage, (cc_h(P1) =< 0 -> clean_object(P1), cc_t(P1):=2, status(P):=0, status(P1):=6 ). element(A,[A|_]). element(A,[_|T]):-element(A,T). draw_object(I):- selection(|S), Selected is (element(I,S) -> 150 else 0), (cc_t(I) mod 4 =:= 0 -> brush(rgb(255,Selected,0)) else (cc_t(I) mod 4 =:= 1 -> brush(rgb(0,Selected,255)) else fail )), X is floor((cc_x(I)-G_PosX)*G_Zoom), Y is floor((cc_y(I)-G_PosY)*G_Zoom), Size is floor(10*G_Zoom), (cc_t(I) < 100 -> rect(X-Size,Y-Size,X+Size,Y+Size) else ellipse(X-Size//2,Y-Size//2,X+Size//2,Y+Size//2) ). draw_shell(I,Clean):- (Clean =:= 1 -> brush(system_color(window)) else brush(rgb(0,0,0)) ), X is floor((tar_x(I)-G_PosX)*G_Zoom), Y is floor((tar_y(I)-G_PosY)*G_Zoom), Size is floor(5*G_Zoom), ellipse(X-Size//2,Y-Size//2,X+Size//2,Y+Size//2). clean_object(I):- brush(system_color(window)), X is floor((cc_x(I)-G_PosX)*G_Zoom), Y is floor((cc_y(I)-G_PosY)*G_Zoom), Size is floor(10*G_Zoom), (cc_t(I) < 100 -> rect(X-Size,Y-Size,X+Size,Y+Size) else ellipse(X-Size//2,Y-Size//2,X+Size//2,Y+Size//2) ). draw_list([H|T],Pos):- (cc_t(H) mod 4 =:= 0 -> color_text(_,rgb(255,0,0)) else color_text(_,rgb(0,0,255)) ), (cc_t(H) < 100 -> Text is "Palace (" + born(H)+ ")" else Text is "Soldier" + (status(H)=:=4->" (move)" else (status(H)//2=:=1->" (attack)" else "")) ), (cc_t(H) =:= 2 -> draw_list(T,Pos) else text_out(0,Pos,Text+" "+cc_h(H)+"%"), draw_list(T,Pos+20) ). find_object(A,B,P,Dist):- for(P,0,G_CC-1), cc_t(P) mod 4 =\= 2, (cc_t(P) < 100 -> abs(cc_x(P)-A) < 10+Dist, abs(cc_y(P)-B) < 10+Dist else (cc_x(P)-A)**2+(cc_y(P)-B)**2 < (5+Dist)**2 ). find_another_object(A,B,Obj,Dist):- find_object(A,B,P,Dist), P=\=Obj. find_in_rect(A,B,C,D,P):- for(P,0,G_CC-1), cc_t(P) mod 4 =\= 2, cc_x(P)>A,cc_x(P)B,cc_y(P) (cc_x(P)-cc_x(Enemy))**2 + (cc_y(P)-cc_y(Enemy))**2 < 10000 ), random(100)<50. find_place(X2, Y2, A, B, P, Dist):- ( not(find_another_object(cc_x(P)+A, cc_y(P)+B, P, Dist)) -> X2 is cc_x(P)+A, Y2 is cc_y(P)+B else ( not(find_another_object(cc_x(P)-B , cc_y(P)+A, P, Dist)) -> X2 is cc_x(P)-B, Y2 is cc_y(P)+A else ( not(find_another_object(cc_x(P)+B, cc_y(P)-A, P, Dist)) -> X2 is cc_x(P)+B, Y2 is cc_y(P)-A else fail ))). find_new_object(New):- (G_CC New:=G_CC, G_CC:=G_CC+1 else find_dead_obj(New) ). find_dead_obj(P):- for(P,0,G_CC-1), cc_t(P) mod 4 =:= 2, not(in_fire(P)), not(selection(|List), element(P, List)). in_fire(Obj):- for(P,0,G_CC-1), attack(P) =:= Obj, status(P) mod 2 =:= 1.