Kali ini saya akan berbagi tentang bagaimana membangun sebuah game, dan pada tulisan ini saya akan membahas game catur yang telah saya buat sendiri pada Tugas di kampus saya.
1.
Bahasa dan Program Editor
Permainan Horse chess ini menggunakan
bahasa pemrograman Prolog, dengan program editor yang saya gunakan adalah
Strawberry Prolog.
2.
Initial State
Initial State
yang digunakan sebagai acuan untuk membuat program Horse chess adalah pada
buah catur yang berisi mayoritas kuda.
Di sini saya menggunakan papan catur biasa tetapi tiap-tiap perwiranya
diganti dengan kuda kecuali ratu. Pion atau bidak terletak dibaris depan
selayaknya catur pada umumnya, dan kuda dibaris belakang menemani 1 raja dan 1
ratu.
Game ini akan mengasah otak pemainnya. Pemain dipaksa
untuk menerapkan strategi yang tepat untuk memenangkan game ini. Permainan ini
hanya dapat dimainkan oleh satu pemain, sedangkan Komputer bertindak sebagai
lawan.
3.
Aturan (Rule)
Setiap permainan pasti memiliki
aturan, begitu juga dengan permainan ini.
Ada beberapa aturan yang terdapat dalam permainan ini, diantaranya
adalah :
- pemain (user) dapat menentukan akan bermain dengan warna putih atau hitam, dan seperti catur pada umumnya, putih jalan terlebih dahulu.
- Pemain hanya dapat melangkah satu kali kemudian komputer yang mendapat giliran melangkah, begitu seterusnya.
- Disini hanya ada 4 tipe buah catur, yaitu : pion, kuda, ratu dan raja.
- Langkah pion yaitu jalan 1 langkah kedepan dengan kondisi petak didepan harus kosong (tidak ada yang menghalangi). Jika ingin memakan lawan, pion melangkah diagonal kedepan sebanyak 1 petak.
- Ketika pion berhasil berjalan sampai garis belakang daerah lawan, maka pion secara otomatis berganti dengan ratu.
- Langkah kuda yaitu membentuk huruf L.
- Langkah ratu yaitu vertical, horizontal dan diagonal.
- Langkah raja sama dengan ratu tetapi hanya boleh melangkah 1 petak saja.
- komputer diberi pembelajaran untuk menghalagi jalan user mencapai tujuan (goal).
- komputer juga diberi pembelajaran untuk memenangkan permaianan ini
- Untuk memenangkan permainan ini, pemain harus membuat raja lawan tidak dapat mengelak untuk dimakan (skak mat).
3.
Tujuan ( Goal )
Tujuan (goal)
untuk menyelesaikan permainan ini adalah membuat
Lawan menyerah dengan
membuat raja tidak dapat mengelak untuk dimakan.
4.
Kecerdasan Buatan ( AI )
Kecerdasan buatan atau sering
disebut sebagai AI pada permaianan ini terletak pada computer, yang bertindak
sebagai lawan. Computer akan berusaha mengalakan pemain (user) dan dapat
menyusun strategi sendiri agar menjadi pemenang.
5. Batas
Usia
Semua orang
dapat menjadi pemain (user) dan memainkan permainan
ini. Karena permainan ini
mengasah keterampilan otak dalam menyusun strategi, maka tidak ada batasan umur
yang diberikan.
6. Strawberry
Prolog
Strawberry Prolog merupakan sebuah
bahasa pemrograman logika yang memiliki Object Oriented Language. Pada prolog
ini tidak terdapat prosedur, hanya terdapat kumpulan data yang akan diolah.
Untuk menggunakan strawberry prolog tidak dilakukan instalasi. Programmer dapat
meng-unduhnya secara gratis di website resminya. Namun karena penggunaannya
yang gratis, pada strawberry prolog ini, games horse chess tidak dapat
membentuk sebuah file execute (exe). Jadi program dapat dijalankan dengan
membuka file strawberry prolog (spj) di dalam strawberry prolog itu sendiri.
7. Analisa
Pembuatan Program
Pembuatan
permainan ini sebenarnya cukup rumit tetapi akan mudah untuk dipelajari,
langkah pertama tentu saya membuat desain gambar sebuah papan catur 8 x 8 kotak
yang berselang-seling dengan warna coklat muda dan coklat tua. Kemudian saya
membuat desain untuk pion putih dan hitam. Lalu membuat desain untuk kuda putih
dan hitam, membuat ratu untuk putih dan hitam dan yang terakhir adalah raja
putih dan hitam yang berbentuk seperti Pegasus (kuda bersayap).
Setelah semua gambar
visual yang dibutuhkan selesai dibuat, kita hanya tinggal “memanggil” gambar
tersebut kedalam prolog pada beberapa perintah. Perlu diingat banhwa file
gambar tersebut harus didalam folder yang sama dengan listing program.spj yang
akan kita buat.
Kemudian saya
memberikan hak langkah untuk masing-masing buah catur dengan beberapa kondisi
dan aturan didalamnya.lalu saya membuat beberapa level kecerdasan AI yaitu
beginner, normal, advanced dan expert yang tentunya memiliki tingkat kesulitan
untuk dikalahkan yang berbeda-beda.
Kemudian saya memberikan aturan khusus untuk raja, yaitu
ketika raja berhasil dimakan, maka permainan berakhir. Untuk lebih jelasnya
saya telah menyiapkan listing program pada lembar selanjutnya.
1. Kesimpulan
Permainan
horse chess yang saya buat ini adalah sebuah permainan hiburan yang juga dapat
mengasah otak. Karena pemain harus menyusun strategi agar dapat mengalahkan AI
yang saya buat pada lawan (computer)
2. Saran
Untuk setiap pemain (user) yang
memainkan permainan ini, diharapkan lebih teliti serta dapat menggunakan strategi
yang tepat dan cerdas agar dapat mengalahkan AI pada komputer
4.
Listing Program :
% If you want to understand this
program look at
% its rough variant "chess rough.pro".
% It is easier to understand because
% "Chess.spj" contains too
many details.
level(1, 2, 1, 5).
level(2, 3, 3, 15).
level(3, 4, 6, 30).
level(4, 5, 30, 150).
?-
G_AuCh=0,
G_Level=2,
G_Deep=0,
G_Move=0,
G_Forward=0,
G_I=0,
G_Play_with_Blacks=0,
G_Play_with_Computer=1,
array(val,100,0),
array(maximum,100,0),
array(i,1000,0),
array(j,1000,0),
array(x,1000,0),
array(y,1000,0),
array(val2,1000,0),
array(index,1000,0),
G_chessboard is
bitmap_image("chess_pic\\chessboard.bmp",_),
G_squareW is
bitmap_image("chess_pic\\squareW.bmp",_),
G_squareB is
bitmap_image("chess_pic\\squareB.bmp",_),
G_PawnW1 is
bitmap_image("chess_pic\\PawnW1.bmp",_),
G_PawnW2 is
bitmap_image("chess_pic\\PawnW2.bmp",_),
G_PawnB1 is bitmap_image("chess_pic\\PawnB1.bmp",_),
G_PawnB2 is
bitmap_image("chess_pic\\PawnB2.bmp",_),
G_KingW1 is
bitmap_image("chess_pic\\KingW1.bmp",_),
G_KingW2 is
bitmap_image("chess_pic\\KingW2.bmp",_),
G_KingB1 is
bitmap_image("chess_pic\\KingB1.bmp",_),
G_KingB2 is
bitmap_image("chess_pic\\KingB2.bmp",_),
G_QueenW1 is
bitmap_image("chess_pic\\QueenW1.bmp",_),
G_QueenW2 is
bitmap_image("chess_pic\\QueenW2.bmp",_),
G_QueenB1 is
bitmap_image("chess_pic\\QueenB1.bmp",_),
G_QueenB2 is
bitmap_image("chess_pic\\QueenB2.bmp",_),
G_KnightW1 is bitmap_image("chess_pic\\KnightW1.bmp",_),
G_KnightW2 is
bitmap_image("chess_pic\\KnightW2.bmp",_),
G_KnightB1 is
bitmap_image("chess_pic\\KnightB1.bmp",_),
G_KnightB2 is
bitmap_image("chess_pic\\KnightB2.bmp",_),
window(G_Win,_,chess_func(_),"Horse Chess",10,150,512,550).
levelm(init):-
menu(normal,_,_,l2(_),"&Beginner"),
menu(checked,_,_,l3(_),"&Normal"),
menu(normal,_,_,l4(_),"&Advanced"),
menu(normal,_,_,l5(_),"&Expert"),
menu(separator, _,_,fail(_),_),
menu(normal,_,_,automatic_change(_),"Automatic change of the Deep").
l2(press):-change_level(1).
l3(press):-change_level(2).
l4(press):-change_level(3).
l5(press):-change_level(4).
automatic_change(press):-
G_AuCh:=1-G_AuCh,
(G_AuCh=0->
modify_menu(G_Menu1,6,normal,_)
else
modify_menu(G_Menu1,6,checked,_)
).
change_level(M):-
G_Deep:=0,
modify_menu(G_Menu1,G_Level,normal,_),
G_Level:=M, modify_menu(G_Menu1,M,checked,_).
changem(init):-
menu(normal,_,_,play_with_blacks(_),"&Play with Blacks"),
menu(checked,_,_,play_with_computer(_),"&Play with the computer").
play_with_blacks(press):-
(G_Play_with_Computer=0->
message("", "You can change the side only when you play with the
computer!", s)
else
change_side,
pos(G_Move, C1, WantsStalemate, Pos),
G_WantsStalemate:=0-WantsStalemate,
opposite(C1, C2),
computer(C1,C2,Pos)
).
change_side:-
G_Play_with_Blacks:=1-G_Play_with_Blacks,
(G_Play_with_Blacks=0->
modify_menu(G_Menu2,1,normal,_)
else
modify_menu(G_Menu2,1,checked,_)
).
play_with_computer(press):-
G_Play_with_Computer:=1-G_Play_with_Computer,
(G_Play_with_Computer=0->
modify_menu(G_Menu2,2,normal,_)
else
modify_menu(G_Menu2,2,checked,_)
).
back(press):-
G_Move:=G_Move - 1,
(G_Move=0->
modify_menu(G_Win,3,grayed,_),
draw_menu_bar(_)
),
(G_Forward=0->
modify_menu(G_Win,4,normal,_),
draw_menu_bar(_)
),
G_Forward:=G_Forward + 1,
set_some_text,
update_window(_).
forward(press):-
(G_Move=0->
modify_menu(G_Win,3,normal,_),
draw_menu_bar(_)
),
G_Move:=G_Move + 1,
G_Forward:=G_Forward - 1,
(G_Forward=0->
modify_menu(G_Win,4,grayed,_),
draw_menu_bar(_)
),
set_some_text,
update_window(_).
set_some_text:-
pos(G_Move, C, _, _),
(G_Play_with_Blacks=\=true_value(C=b)->
change_side
),
(C=b->
set_text("Play with Blacks", _)
else (C=w->
set_text("Play with Whites", _)
else
set_text("Game Over", _)
)).
set_pos(C, Pos) :-
(G_Move=0->
modify_menu(G_Win,3,normal,_),
draw_menu_bar(_)
),
(G_Forward>0->
modify_menu(G_Win,4,grayed,_),
draw_menu_bar(_)
),
G_Move:=G_Move+1,
G_Forward:=0,
write(pos(G_Move, C, G_WantsStalemate, Pos)),nl,
retractall(pos(G_Move,_,_,_)),
assert(pos(G_Move,C,G_WantsStalemate,Pos)).
chess_func(init):-
menu(pop_up, G_Menu1,_,levelm(_),"&Level"),
menu(pop_up, G_Menu2,_,changem(_),"&Change"),
menu( right, _, _, back(_), "&Back"),
menu( right, _, _,
forward(_),
"&Forward"),
modify_menu(G_Win,3,grayed,_),
modify_menu(G_Win,4,grayed,_).
chess_func(paint):-
draw_bitmap(0,0,G_chessboard,_,_),
fail.
chess_func(paint):-
pos(G_Move, _, _, Pos),
mem(Row, Pos,J),
mem(Fig, Row,I),
draw_fig(Fig,I,J),
fail.
chess_func(mouse_click(X,Y)):-
I :=X//50,
J :=Y//50,
I>0, I=<8,
J>0, J=<8,
pos(G_Move, C1, WantsStalemate, Pos),
opposite(C1, C2),
mem(Row,Pos,J),
mem(Fig,Row,I),
(G_I=0 ->
Fig=[_|C1],
G_Fig:=Fig,
clean_field(I, J),
G_I:=I,
G_J:=J
else (can_move(G_Fig,G_I,G_J,I,J,Pos,Fig2),
not(Fig2=[_|C1])->
move0(G_I,G_J,Pos,I,J,Pos2),
(check(C1, C2, Pos2)->
message("Bad move", "You are in check after this move", !),
draw_fig(G_Fig,G_I,G_J),
G_I:=0,
fail
),
(J/\6=:=0->
(G_Fig=[p|C1]->
draw_fig([q|C1],I,J)
else (G_Fig=[k|C1], abs(G_I-I)=:=2 ->
(I=3, Xm=4, Xf=1; I=7, Xm=6, Xf=8),
clean_field(Xf, J),
draw_fig([r|C1],Xm,J),
draw_fig([k|C1],I,J)
else
draw_fig(G_Fig,I,J)
))
else
draw_fig(G_Fig,I,J)
),
val(Fig2,Val),
G_WantsStalemate:=WantsStalemate+Val,
(check(C2, C1, Pos2), not(not_mate(C2, C1, Pos2))->
set_pos(n,Pos2),
set_text("Mate. You won!", _),
message("Congratulations", "You won!", !),
fail
),
(G_Play_with_Computer=1->
computer(C2,C1,Pos2)
else
change_side,
G_WantsStalemate:=0-G_WantsStalemate,
set_pos(C2, Pos2),
set_text(xy(G_I, G_J)+":"+xy(I, J)+ (G_Play_with_Blacks=1-> " (Play with Blacks)" else ""), _),
G_I:=0
)
else
draw_fig(G_Fig,G_I,G_J),
G_I:=0
)).
computer(C2,C1,Pos2):-
G_I:=0,
set_text("...", _),
G_I1:=0,
(G_Deep=0->level(G_Level,Deep,_,_), G_Deep:=Deep),
write("Deep="+G_Deep),nl,
chronometer(_),
chronometer_steps(_),
maximum(G_Deep):= -20000,
Moves:=0,
(play(C2,C1,Pos2,G_Deep,Moves); true),
chronometer(Time),
chronometer_steps(Steps),
beep,
write(maximum(G_Deep)+" for "+Time/1000+" seconds ("+Steps+" steps)"),nl,
(G_AuCh=1->
level(G_Level,_,Minimum,Maximun),
(Time<1000*Minimum->
G_Deep:=G_Deep+1,
write("Deep+1="+G_Deep),nl
else (Time>1000*Maximun, G_Deep>2->
G_Deep:=G_Deep- 1,
write("Deep-1="+G_Deep),nl
))
),
(G_I1=0->
set_pos(n, Pos2),
set_text("Stalemate", _),
message("Stalemate", "I am in stalemate. This gane is draw.", !),
fail
),
mem(Row1,Pos2,G_J1),
mem(Fig,Row1,G_I1),
can_move(Fig,G_I1,G_J1,G_I2,G_J2,Pos2,Fig2),
val(Fig2,Val),
G_WantsStalemate:=G_WantsStalemate-Val,
move0(G_I1,G_J1,Pos2,G_I2,G_J2,Pos3),
clean_field(G_I1, G_J1),
mem(Row2,Pos3,G_J2),
mem(BFig,Row2,G_I2),
(BFig=[k|C2], abs(G_I1-G_I2)=:=2 ->
(G_I2=3, XXm=4, XXf=1; G_I2=7, XXm=6, XXf=8),
clean_field(XXf, G_J2),
draw_fig([r|C2],XXm,G_J2),
draw_fig([k|C2],G_I2,G_J2)
else
draw_fig(BFig,G_I2,G_J2)
),
(check(C1, C2, Pos3)->
(not_mate(C1, C2, Pos3)->
set_text("Check", _)
else
set_pos(n, Pos3),
set_text("You are Mate!", _),
message("Mate. Game over", "Sorry but you lost this set.", s),
fail
)
else
set_text(xy(G_I1, G_J1)+":"+xy(G_I2, G_J2)+ (G_Play_with_Blacks=1-> " (Play with
Blacks)" else
""), _)
),
(not(mem(Row3,Pos3,J1), mem([F1|C1],Row3,I1), can_move([F1|C1],I1,J1,_,_,Pos3,Fig3),
not(Fig3=[_|C1]))->
set_pos(n, Pos3),
set_text("Stalemate", _),
message("Stalemate", "You are in stalemate. This game is
draw.", !),
fail
),
(not(mem(Row4,Pos3,_), mem([F2|_],Row4,_), F2\=k)->
set_pos(n, Pos3),
set_text("Tie", _),
message("Tie", "This game is draw.", !),
fail
),
set_pos(C1, Pos3).
play(C1,C2,Pos,Deep,Moves):-
Deep1
is Deep - 1,
(Deep1=0->
(val(Deep):=35;
mem(Row,Pos,J),
mem([Fig|C1],Row,I),
can_move([Fig|C1],I,J,X,Y,Pos,[Fig2|C2]),
take_val(Fig,Fig2,Val2,C1,C2,X,Y,Pos),
val(Deep):=Val2)
else
Moves2:=Moves,
all_moves(C1,Pos,Deep,I,J,X,Y,Val2,Moves,Moves2),
move(I,J,Pos,X,Y,Pos2,Val2),
val(Deep):=Val2,
(Val2>5000->
(Deep=:=G_Deep- 1, check(C2, C1, Pos)->
maximum(Deep1):= -5000
else
maximum(Deep1):=0
)
else
maximum(Deep1):= -20000,
(play(C2,C1,Pos2,Deep1,Moves2); true),
(maximum(Deep1) =:= -20000->
(check(C2, C1, Pos2)->
maximum(Deep1):= -10000-Deep
else
maximum(Deep1):= (1 - 2* ((G_Deep-Deep1) mod 2))*G_WantsStalemate
)
)
)
),
%(Deep=G_Deep-> write(xy(I,J)+":"+xy(X,Y)+" is "+
(val(Deep)-maximum(Deep1))), nl),
(maximum(Deep)<val(Deep)-maximum(Deep1)->
% =< in order to see all best
maximum(Deep):=val(Deep)-maximum(Deep1),
(Deep=G_Deep->
write(xy(I,J)+":"+xy(X,Y)+"
is "+ (val(Deep)-maximum(Deep1))), nl,
G_I1:=I, G_J1:=J,
G_I2:=X, G_J2:=Y,
fail
else (maximum(Deep+1)<val(Deep+1)-maximum(Deep)-> % =< in order to see all best
fail
%else
%write(Deep) % alpha-beta cutting
))
else
fail
),
!,
fail.
all_moves(C1,Pos,Deep,_,_,_,_,_,Moves,Moves2):-
mem(Row,Pos,J),
mem([Fig|C1],Row,I),
Sum1:=0,
can_hit([Fig|C1],I,J,Pos,shadow,no,Sum1),
can_move([Fig|C1],I,J,X,Y,Pos,Fig2),
not(Fig2=[_|C1]),
(Fig2=[p|_]->
Val is (C1=w-> 60+20*Y else 240- 20*Y)
else
val(Fig2,Val)
),
Val2 is Val-Sum1+Deep* (1+sign(Val//18- 1)), % 18 is val(p)
find_the_right_place(Val2,Moves,Moves2,Place),
i(Moves2):=I, j(Moves2):=J,
x(Moves2):=X, y(Moves2):=Y,
val2(Moves2):=Val2,
index(Place):=Moves2,
Moves2:=Moves2+1,
fail.
all_moves(_,_,_,I,J,X,Y,Val2,Moves,Moves2):-
for(N, Moves, Moves2- 1),
I is i(index(N)), J is j(index(N)),
X is x(index(N)), Y is y(index(N)),
Val2 is val2(index(N)).
find_the_right_place(Val2,M,M,M):- !.
find_the_right_place(Val2,Moves,Moves2,Place):-
MovesP is Moves2- 1,
(val2(index(MovesP))<Val2->
index(Moves2):=index(MovesP),
find_the_right_place(Val2,Moves,MovesP,Place)
else
Moves2=Place
).
can_hit([Fig|C1],I,J,Pos,_,Try,Sum):- % the figure hits
can_move([Fig|C1],I,J,_,_,Pos,F),
(F=[Fig2|C]->
(C=C1->
Sum:=Sum+8
else
val([Fig2|_],Val2),
val([Fig|_],Val1),
(Val1<Val2->
(Fig2=k->
(Try=no;
not_mate(C, C1, Pos)->
Sum:=Sum+50
else
Sum:=Val2
)
else
Sum:=Sum+33
)
else
Sum:=Sum+12
)
)
else
Sum:=Sum+4
),
fail.
can_hit([Fig|C1],I,J,Pos,Shadow,_,Sum):- % other figures hit it
can_move([F|C_1],I,J,I0,J0,Pos,[F|C_2]),
not(F=p, C_1=C_2),
not(F=k, C_1=C_2),
(C_2=C1->
Sum:=Sum+ 4 % 8-4
else
val([F|_],Val2),
val([Fig|_],Val1),
(Val1>Val2->
(Fig=k->
Sum:=Sum- 46 % 50-4
else
Sum:=Sum- 29 % 33-4
)
else
Sum:=Sum- 8 % 12-4
)
),
throw_shadow(Shadow,[F|C_2],I0,J0,I,J,Pos,SumT),
(C_2=C1->
Sum:=Sum-SumT
else
Sum:=Sum+SumT
),
fail.
can_hit(_,_,_,_,_,_,_).
throw_shadow(shadow,[F|C_2],I1,J1,I2,J2,Pos,Sum):-
Sum:=0,
(F=r; F=q),
(I1=I2->
(J1<J2->
move_down(I2,J2,_,_,Pos,Fig)
else
move_up(I2,J2,_,_,Pos,Fig)
)
else (J1=J2->
(I1<I2->
move_right(I2,J2,_,_,Pos,Fig)
else
move_left(I2,J2,_,_,Pos,Fig)
)
else
fail
)),
hit([F|C_2],Fig,Sum).
throw_shadow(shadow,[F|C_2],I1,J1,I2,J2,Pos,Sum):-
(F=b; F=q),
(I1+J1=:=I2+J2->
(I1<I2->
move_right_up(I2,J2,_,_,Pos,Fig)
else
move_left_down(I2,J2,_,_,Pos,Fig)
)
else (I1-J1=:=I2-J2->
(I1<I2->
move_right_down(I2,J2,_,_,Pos,Fig)
else
move_left_up(I2,J2,_,_,Pos,Fig)
)
else
fail
)),
hit([F|C_2],Fig,Sum).
throw_shadow(shadow,[_|_],_,_,_,_,_,_).
hit([Fig|C1],F,Sum):-
(F=[Fig2|C]->
(C=C1->
Sum:=Sum+8
else
val([Fig2|_],Val2),
val([Fig|_],Val1),
(Val1<Val2->
(Fig2=k->
Sum:=Sum+50
else
Sum:=Sum+33
)
else
Sum:=Sum+12
)
)
else
Sum:=Sum+4
),
fail.
move(I1,J1,Pos1,I2,J2,Pos2,Sum):-
mem(Row, Pos1, J1),
mem([F1|C1], Row, I1),
replace(f, Row,
Row2,I1),
replace(Row2, Pos1, Pos1a, J1),
mem(Row3, Pos1a, J2),
(J2/\6=:=0->
(F1=p->
replace([q|C1], Row3,
Row4, I2)
else (F1=k, abs(I1-I2)=:=2 ->
(I2=3, Xm=4, Xf=1; I2=7, Xm=6, Xf=8),
Sum:=Sum+50,
replace(f, Row3,
Row3a, Xf),
replace([r|C1],
Row3a, Row3b, Xm),
replace([F1|C1],
Row3b, Row4, I2)
else
replace([F1|C1], Row3,
Row4, I2)
))
else
replace([F1|C1], Row3,
Row4, I2)
),
replace(Row4, Pos1a, Pos2,J2),
(mem([F2|C2], Row3,
I2)->
Sum1:=0,
can_hit([F2|C2],I2,J2,Pos2,no,no,Sum1),
Sum:=Sum-Sum1,
can_hit([F1|C1],I2,J2,Pos2,no,try,Sum)
else
can_hit([F1|C1],I2,J2,Pos2,shadow,try,Sum)
).
move0(I1,J1,Pos1,I2,J2,Pos2):-
mem(Row, Pos1, J1),
mem([F1|C1], Row, I1),
replace(f, Row,
Row2,I1),
replace(Row2, Pos1, Pos1a, J1),
mem(Row3, Pos1a, J2),
(J2/\6=:=0->
(F1=p->
replace([q|C1], Row3,
Row4, I2)
else (F1=k, abs(I1-I2)=:=2 ->
(I2=3, Xm=4, Xf=1; I2=7, Xm=6, Xf=8),
replace(f, Row3,
Row3a, Xf),
replace([r|C1],
Row3a, Row3b, Xm),
replace([F1|C1],
Row3b, Row4, I2)
else
replace([F1|C1], Row3,
Row4, I2)
))
else
replace([F1|C1], Row3,
Row4, I2)
),
replace(Row4, Pos1a, Pos2,J2).
val(f,0).
val(p,18). % Pawn move
val(d,35). % Pawn double move = 2*val(p)-1
val([p|_],100).
val([h|_],300).
val([q|_],1000).
val([n|_],600). % new queen
val([t|_],700). % new queen and take
val([k|_],10000).
take_val(p,p,60|_). take_val(p,h,250|_). take_val(p,q,950|_). take_val(p,k,10000|_).
take_val(k,p,100|_). take_val(k,h,300|_).
take_val(k,q,1000|_). take_val(k,k,10000|_).
take_val(h|T):-
evaluate(300|T).
take_val(q|T):-
evaluate(1000|T).
evaluate(Val1,Fig,Val,C1,C2,X,Y,Pos):-
val([Fig|_],Val2),
(Val2>Val1->
Val is Val2 - Val1//2
else (can_move([F|C1],X,Y,_,_,Pos,[F|C2])->
Val=50
else
val([Fig|_],Val)
)).
%pos(0,w,0,[[rb,hb,bb,qb,kb,bb,hb,rb],[f,pb,f,f,f,f,pb,f],[f,f,f,pb,f,pb,f,f],[pb,f,pb,qw,f,f,f,pb],[f,f,f,f,pw,f,f,f],[f,pw,hw,f,f,hw,f,f],[pw,f,pw,f,f,pw,pw,pw],[rw,f,bw,f,kw,bw,f,rw]]).
pos(0, w, 0,
[[hb,hb,hb,qb,kb,hb,hb,hb],
[pb,pb,pb,pb,pb,pb,pb,pb],
[f,f,f,f,f,f,f,f],
[f,f,f,f,f,f,f,f],
[f,f,f,f,f,f,f,f],
[f,f,f,f,f,f,f,f],
[pw,pw,pw,pw,pw,pw,pw,pw],
[hw,hw,hw,qw,kw,hw,hw,hw]]).
clean_field(I, J):-
( (I+J) mod 2 =:= 0->
draw_bitmap(50*I,50*J,G_squareW,_,_)
else
draw_bitmap(50*I,50*J,G_squareB,_,_)
).
draw_fig(Fig,I,J):-
N is 1+ (I+J) mod 2,
fig(Fig, N, Bitmap),
draw_bitmap(I*50,J*50,Bitmap,_,_).
fig(pb, 1,
G_PawnB1).
fig(pw, 1,
G_PawnW1).
fig(kb, 1,
G_KingB1).
fig(kw, 1,
G_KingW1).
fig(qb, 1,
G_QueenB1).
fig(qw, 1,
G_QueenW1).
fig(hb, 1,
G_KnightB1).
fig(hw, 1,
G_KnightW1).
fig(pb, 2,
G_PawnB2).
fig(pw, 2,
G_PawnW2).
fig(kb, 2,
G_KingB2).
fig(kw, 2,
G_KingW2).
fig(qb, 2,
G_QueenB2).
fig(qw, 2, G_QueenW2).
fig(hb, 2,
G_KnightB2).
fig(hw, 2,
G_KnightW2).
R is xy(X, Y):- R:=string_from_ASCII(X+first_ASCII("A")- 1)+ (9-Y).
mem(E,[E,_,_,_,_,_,_,_],1).
mem(E,[_,E,_,_,_,_,_,_],2).
mem(E,[_,_,E,_,_,_,_,_],3).
mem(E,[_,_,_,E,_,_,_,_],4).
mem(E,[_,_,_,_,E,_,_,_],5).
mem(E,[_,_,_,_,_,E,_,_],6).
mem(E,[_,_,_,_,_,_,E,_],7).
mem(E,[_,_,_,_,_,_,_,E],8).
replace(X,[_,A,B,C,D,E,F,G],[X,A,B,C,D,E,F,G],1).
replace(X,[A,_,B,C,D,E,F,G],[A,X,B,C,D,E,F,G],2).
replace(X,[A,B,_,C,D,E,F,G],[A,B,X,C,D,E,F,G],3).
replace(X,[A,B,C,_,D,E,F,G],[A,B,C,X,D,E,F,G],4).
replace(X,[A,B,C,D,_,E,F,G],[A,B,C,D,X,E,F,G],5).
replace(X,[A,B,C,D,E,_,F,G],[A,B,C,D,E,X,F,G],6).
replace(X,[A,B,C,D,E,F,_,G],[A,B,C,D,E,F,X,G],7).
replace(X,[A,B,C,D,E,F,G,_],[A,B,C,D,E,F,G,X],8).
check(C1, C2, Pos):-
mem(Row,Pos,J),
mem([k|C1],Row,I),
can_move([Fig|C1],I,J,_,_,Pos,[Fig|C2]).
not_mate(C1, C2, Pos):-
mem(Row,Pos,J),
mem([Fig|C1],Row,I),
can_move([Fig|C1],I,J,X,Y,Pos,Fig2),
not(Fig2=[_|C1]),
move0(I,J,Pos,X,Y,Pos2),
not(check(C1, C2, Pos2)).
opposite(w, b).
opposite(b, w).
can_move([h|_], X1,Y1,X2,Y2,Pos,Fig):-
(X2 is X1+1; X2 is X1 - 1),
(Y2 is Y1+2; Y2 is Y1 - 2),
mem(Row,Pos,Y2),
mem(Fig,Row,X2).
can_move([h|_], X1,Y1,X2,Y2,Pos,Fig):-
(X2 is X1+2; X2 is X1 - 2),
(Y2 is Y1+1; Y2 is Y1 - 1),
mem(Row,Pos,Y2),
mem(Fig,Row,X2).
can_move([k|Color], X1,Y1,X2,Y2,Pos,Fig):-
(X2 is X1+1; X2 is X1 - 1; X2=X1),
(Y2 is Y1+1; Y2 is Y1 - 1;Y2=Y1),
not(X1=X2,Y1=Y2),
mem(Row,Pos,Y2),
mem(Fig,Row,X2),
opposite(Color, C2),
(Fig=[k| C2];
not(can_move([F|Color],X2,Y2,_,_,Pos,[F|C2]))).
can_move([k|Color], 5,Y,X2,Y,Pos,f):-
(Y = 1, Color=b, C2=w; Y= 8, Color=w, C2=b),
mem(Row,Pos,Y),
(X2 = 3, mem(f,Row,2), Xn=4, Xr=1; X2 = 7, Xn=6, Xr=8),
mem(f,Row,X2),
mem(f,Row,Xn),
mem([r|Color],Row,Xr),
not(can_move([Fig|Color],X2,Y,_,_,Pos,[Fig|C2])),
not(can_move([Fig|Color],Xn,Y,_,_,Pos,[Fig|C2])),
not(can_move([Fig|Color], 5,Y,_,_,Pos,[Fig|C2])).
can_move(pw, X,Y1,X,Y2,Pos,Fig):-
Yn is Y1 - 1,
mem(Row,Pos,Yn),
mem(f,Row,X),
(Y2=Yn, (Y1=2->Fig=nb else Fig=p)
;
Y1=7, mem(Row2,Pos,5), mem(f,Row2,X), Y2=5, Fig=d
).
can_move(pb, X,Y1,X,Y2,Pos,Fig):-
Yn is Y1 + 1,
mem(Row,Pos,Yn),
mem(f,Row,X),
(Y2=Yn, (Y1=7->Fig=nw else Fig=p)
;
Y1=2, mem(Row2,Pos,4), mem(f,Row2,X), Y2=4, Fig=d
).
can_move(pw, X1,Y1,X2,Y2,Pos,[F1|C]):-
Y2 is Y1 - 1,
mem(Row,Pos,Y2),
(X2 is X1+1;X2 is X1 - 1),
mem([F2|C],Row,X2),
(Y2=1, F2\=k->F1=t else F1=F2).
can_move(pb, X1,Y1,X2,Y2,Pos,[F1|C]):-
Y2 is Y1 + 1,
mem(Row,Pos,Y2),
(X2 is X1+1;X2 is X1 - 1),
mem([F2|C],Row,X2),
(Y2=8, F2\=k->F1=t else F1=F2).
can_move([r|_], X1,Y1,X2,Y2,Pos,Fig):-
move_up(X1,Y1,X2,Y2,Pos,Fig);
move_down(X1,Y1,X2,Y2,Pos,Fig);
move_left(X1,Y1,X2,Y2,Pos,Fig);
move_right(X1,Y1,X2,Y2,Pos,Fig).
can_move([b|_], X1,Y1,X2,Y2,Pos,Fig):-
move_left_up(X1,Y1,X2,Y2,Pos,Fig);
move_right_down(X1,Y1,X2,Y2,Pos,Fig);
move_left_down(X1,Y1,X2,Y2,Pos,Fig);
move_right_up(X1,Y1,X2,Y2,Pos,Fig).
can_move([q|_], X1,Y1,X2,Y2,Pos,Fig):-
move_up(X1,Y1,X2,Y2,Pos,Fig);
move_down(X1,Y1,X2,Y2,Pos,Fig);
move_left(X1,Y1,X2,Y2,Pos,Fig);
move_right(X1,Y1,X2,Y2,Pos,Fig);
move_left_up(X1,Y1,X2,Y2,Pos,Fig);
move_right_down(X1,Y1,X2,Y2,Pos,Fig);
move_left_down(X1,Y1,X2,Y2,Pos,Fig);
move_right_up(X1,Y1,X2,Y2,Pos,Fig).
move_up(X,Y1,X,Y2,Pos,Fig2):-
Y is Y1 - 1,
mem(Row,Pos,Y),
mem(Fig,Row,X),
(Fig=f ->
(Y2 =Y, Fig2=Fig; move_up(X,Y,X,Y2,Pos,Fig2))
else
Y2=Y, Fig2=Fig
).
move_down(X,Y1,X,Y2,Pos,Fig2):-
Y is Y1 + 1,
mem(Row,Pos,Y),
mem(Fig,Row,X),
(Fig=f ->
(Y2 =Y, Fig2=Fig; move_down(X,Y,X,Y2,Pos,Fig2))
else
Y2=Y, Fig2=Fig
).
move_left(X1,Y,X2,Y,Pos,Fig2):-
X is X1 - 1,
mem(Row,Pos,Y),
mem(Fig,Row,X),
(Fig=f ->
(X2=X, Fig2=Fig; move_left(X,Y,X2,Y,Pos,Fig2))
else
X2=X, Fig2=Fig
).
move_right(X1,Y,X2,Y,Pos,Fig2):-
X is X1 + 1,
mem(Row,Pos,Y),
mem(Fig,Row,X),
(Fig=f ->
(X2=X, Fig2=Fig; move_right(X,Y,X2,Y,Pos,Fig2))
else
X2=X, Fig2=Fig
).
move_left_up(X1,Y1,X2,Y2,Pos,Fig2):-
X is X1 - 1, Y is Y1 - 1,
mem(Row,Pos,Y),
mem(Fig,Row,X),
(Fig=f ->
(X2=X, Y2=Y, Fig2=Fig; move_left_up(X,Y,X2,Y2,Pos,Fig2))
else
X2=X, Y2=Y, Fig2=Fig
).
move_left_down(X1,Y1,X2,Y2,Pos,Fig2):-
X is X1 - 1, Y is Y1 + 1,
mem(Row,Pos,Y),
mem(Fig,Row,X),
(Fig=f ->
(X2=X, Y2=Y, Fig2=Fig; move_left_down(X,Y,X2,Y2,Pos,Fig2))
else
X2=X, Y2=Y, Fig2=Fig
).
move_right_up(X1,Y1,X2,Y2,Pos,Fig2):-
X is X1 + 1, Y is Y1 - 1,
mem(Row,Pos,Y),
mem(Fig,Row,X),
(Fig=f ->
(X2=X, Y2=Y, Fig2=Fig; move_right_up(X,Y,X2,Y2,Pos,Fig2))
else
X2=X, Y2=Y, Fig2=Fig
).
move_right_down(X1,Y1,X2,Y2,Pos,Fig2):-
X is X1 + 1, Y is Y1 + 1,
mem(Row,Pos,Y),
mem(Fig,Row,X),
(Fig=f ->
(X2=X, Y2=Y, Fig2=Fig; move_right_down(X,Y,X2,Y2,Pos,Fig2))
else
X2=X, Y2=Y, Fig2=Fig
).