150 likes | 518 Views
Workshop Project 2 G ame PacMan & Algoritma AI yang Digunakan Musuhnya. Mohammad Zikky, S.ST, M.T. Overview.
E N D
Workshop Project 2Game PacMan & Algoritma AI yang DigunakanMusuhnya Mohammad Zikky, S.ST, M.T
Overview • Pacmanadalahsebuahpermainan video arkade yang cukupterkenal. Cara bermainnyamudahyaitupemain (pacman) diharuskanmemakanmakanan (berbentuktitik-titikkecil) dansebuahbulatanbesar (energizer) sampaihabis di dalamlabirin yang berliku-liku. • Pemainjugaharusmenghindari 4 ‘hantu’ yang berkeliaransecara random untukmenangkappemain. Jikapemainbertemudenganhantu-hantutersebutmakapemaindinyatakangagaldanharusmengulangidariawallagi. • Pergerakan para hantuinidipengaruhiolehkecerdasanbuatanatau Artificial intelligence (AI), dimana para hantudiberikecerdasanuntukmenentukanlangkahdanmengambilkeputusanakanbergerakkemanadenganmenentukanrute yang paling pendek (minimum), tujuannyaadalahmenangkappemain. Setiaphantuharusmemilikipemikiranberbedadanmemilikikemampuanbekerjasamauntukmengejarpemain, sehinggapermainanakantampaklebihmenarik. • PersoalanmendekatikarakterPacmaninidapatdiselesaikandenganberbagaimacamcara, salahsatunyadenganmenggunakanAlgoritma greedy/dijkstra
AlgoritmaDijkstra • Djikstra(dinamaimenurutpenemunya, seorangilmuwankomputer, EdsgerDijkstra), adalahsebuahalgoritmarakus (greedy algorithm) yang dipakaidalammemecahkanpermasalahanjarakterpendek (shortest path problem) untuksebuahgrafberarah (directed graph) denganbobot-bobotsisi (edge weights) yang bernilaitak-negative (wikipedia)DetilpenjelasantentangAlgoritmaDijkstraklikdisini: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
Cara KerjaMusuh (Hantu) padaPacMan • Elemen-elemenalgoritmagreedy padapermasalahanmusuhPacmanadalahsebagaiberikut : • HimpunanKandidat : himpunantitik-titik (node) yang merupakanposisi yang dapatdilaluiolehmusuhPacman • HimpunanSolusi : himpunantitik-titik yang dipilihadalahrute yang berakhirpadaposisikarakterPacman. • FungsiSeleksi : titik (node) yang dipilihsemakinmendekatiposisikarakterPacman. • FungsiLayak : titik yang dipilihdapatdilalui (bukantembokataukaraktermusuh lain) • FungsiObjektif : rute yang dipilihadalahrute yang paling optimum (dalamhalini, paling pendek)
Cara KerjaMusuh (Hantu) padaPacMan • Fungsiseleksipadapersoalaninidapatdijabarkansebagaiberikut: • JikakarakterPacmanada di sebelahkanankaraktermusuhsaatini, makamusuhpindahkekanan, jikatidakpindahkekiri • JikakarakterPacmanada di sebelahataskaraktermusuhsaatini, makamusuhpindahkeatas, jikatidakpindahkebawah • Sebelumkaraktermusuhdipindahkan, terlebihdahuludicekapakahlangkahpemindahantersebutsah (layak), dalamartiantidakadadinding / tembokataukaraktermusuh lain yang menghalangi
KodeSemu / Pseudo Code MusuhPacman • Digunakanduatipevariabelbernama “musuh” dan “pacman” yang masing-masingmerepresentasikankaraktermusuhdankarakterpacman. Masing-masingtipetersebutmemilikiatribut X dan Y yang menunjukkanposisiabsisdanordinattipetersebutpadalabirinpermainanpacman procedure gerakMusuh(m:musuh,p:pacman) { if(p.X() >= m.X and isOK(m.X+1, m.Y)) then pindahKanan(m) else if(p.Y()>= m.Y and (isOK(m.X, m.Y+1)) then pindahAtas(m) else if(isOK(m.X, m.Y - 1) then pindahBawah(m) else if(isOK(m.X-1, Y)) then pindahKiri(m) }
KodeSemu / Pseudo Code MusuhPacman • Fungsilayak : untukmenentukanapakah di posisi x dan y terdapatdindingataukaraktermusuh lain yang menghalangi function isOK(x, y:integer)-> boolean { if(noDinding(x,y) && noMusuh(x,y)) true else false } • Denganalgoritma di atas, karaktermusuhpacmandigerakkanhinggamencapaisuatutitikdalamlabirin yang merupakanpercabangan. JadifungsigerakkanMusuh di atasakandipanggilberulang-ulangsetiapkaraktermusuhsampai di suatupercabangan
ContohKasus • MisalfungsiseleksigerakkanMusuhditerapkanpadamusuhPacmanyang berwarnaoranye (padagambarterlihatsebagaikarakter yang dilingkaridenganlingkaranberwarnaoranye). • Posisikaraktermusuhoranyeberada di sebelahkirikarakterPacmanyang berwarnakuning (m.X < p.X), makakaraktermusuhoranyeseharusnyabergerakkekanan, namunternyataadadinding yang menghalangi, makadilakukanpengecekanlagiterhadapperbandinganposisi Y dandidapatiposisikaraktermusuhoranyeberada di sebelahataskarakterPacman(m.Y > p.Y) dantidakadadindingmaupunkaraktermusuh lain yang menghalangi di atasnya, makakaraktermusuhoranyedipindahkankeatas.
ContohKasus • Diterapkanlagialgoritmagreedy untuk kali kedua, posisikarakteroranyesekarangada di sebelahkirikarakterPacman(m.X < p.X) dantidakada yang menghalangi di sebelahkanannya • Sehinggahasilpergerakannyaadalah: Setelahbergerakkekanan, algoritmagreedy diterapkanlagidankaraktermusuhberada di atasPacman(m.Y > p.Y), makakaraktermusuhdigerakkankebawahsampaibertemudengankarakterPacman
Sekarangcobajalankansource codeberikutkemudianPahami: class entity { public: entity( int x, int y ){ this ->x = x; this ->y = y; } void move_x( int p ){ if( map[y][x+p] == ' ' ) x += p; } void move_y( int p ){ if( map[y+p][x] == ' ' ) y += p; } void move( int p, int q ){ x += p; y += q; } intget_x(){ return x; } intget_y(){ return y; } void draw( char p ){ map[x][y] = p; gotoxy( x, y ); printf( "%c", p ); } private: int x; int y; }; struct walk { short walk_count; short x; short y; short back; }; #include <iostream> #include <stdio.h> #include <windows.h> #include <string> #include <vector> using namespace std; char tmp_map[18][32]; char map[18][32] = { "+#############################+", "| |", "| |", "|## ########### ## #########|", "| | |", "| | |### | | | |", "| | | | |### | | | |", "| | #####| | | ## | |", "| | |### | | |", "| |##### ### ## |", "| ###### ####### ###|", "| |", "|# ### #### ### #######|", "| |", "| |", "| |", "| |", "+#############################+" }; void ShowMap() { for(inti = 0; i < 18; i++) { printf("%s\n",map[i] ); } } void gotoxy( short x, short y ) { HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE) ; COORD position = { x, y } ; SetConsoleCursorPosition( hStdout, position ) ; }
Jalankan Source Code (lanjutan) inti = 0; while( i < BFSArray.size() ){ if( BFSArray[i].x == x && BFSArray[i].y == y ){ walk_queue.clear(); target tmp2; while( BFSArray[i].walk_count != 0 ){ tmp2.x = BFSArray[i].x; tmp2.y = BFSArray[i].y; walk_queue.push_back( tmp2 ); i = BFSArray[i].back; } break; } AddArray( BFSArray[i].x+1, BFSArray[i].y, BFSArray[i].walk_count+1, i ); AddArray( BFSArray[i].x-1, BFSArray[i].y, BFSArray[i].walk_count+1, i ); AddArray( BFSArray[i].x, BFSArray[i].y+1, BFSArray[i].walk_count+1, i ); AddArray( BFSArray[i].x, BFSArray[i].y-1, BFSArray[i].walk_count+1, i ); i++; } BFSArray.clear(); } struct target { short x; short y; }; vector<target> walk_queue; vector<walk> BFSArray; void AddArray( int x, int y, intwc , int back ){ if( tmp_map[y][x] == ' ' || tmp_map[y][x] == '.' ){ tmp_map[y][x] = '#'; walk tmp; tmp.x = x; tmp.y = y; tmp.walk_count = wc; tmp.back = back; BFSArray.push_back( tmp ); } } void FindPath( intsx, intsy, int x, int y ){ memcpy( tmp_map, map, sizeof(map) ); BFSArray.clear(); walk tmp; tmp.x = sx; tmp.y = sy; tmp.walk_count = 0; tmp.back = -1; BFSArray.push_back( tmp);
Jalankan Source Code (lanjutan 2) ShowMap(); gotoxy( x, y ); cout << "T"; int frame = 0; FindPath( ex,ey,x,y ); while( running ){ gotoxy( x, y ); cout << " "; old_x = x; old_y = y; if ( GetAsyncKeyState( VK_UP ) ){ if( map[y-1][x] == '.' ){ y--; pts++; } else if( map[y-1][x] == ' ' ) y--; } if ( GetAsyncKeyState( VK_DOWN ) ){ if( map[y+1][x] == '.' ){ y++; pts++; } else if( map[y+1][x] == ' ' ) y++; } if ( GetAsyncKeyState( VK_LEFT ) ){ if( map[y][x-1] == '.' ){ x--; pts++; } else if( map[y][x-1] == ' ' ) x--; } if ( GetAsyncKeyState( VK_RIGHT ) ){ if( map[y][x+1] == '.' ){ x++; pts++; } else if( map[y][x+1] == ' ' ) x++; } int main() { bool running = true; int x = 15; // hero x int y = 16; // hero y intold_x; intold_y; int ex = 1; intey = 1; int pts = 0; printf("Instruksi:\n1. PanahKananKiriAtasBawahuntukPergerakanAktorPacman\n2. MakanTitik yang di produksimusihuntukmendapatkanpoin\n3. Jangansampaiketangkapmusuh\n\n"); printf("H -> Hard (Sulit)\nN -> Normal (Biasa)\nE -> Easy (Mudah)\n\nMasukkan Level : "); char diffi; intspeedmod = 3; cin >> diffi; if( diffi == 'N' ){ speedmod = 2; }else if( diffi == 'H' ){ speedmod = 1; } system("cls");
Jalankan Source Code (lanjutan 3) system("cls"); printf("AndaKalah /n SkorAkhirAnda : %i", pts ); cin.get(); cin.get(); cin.get(); cin.get(); cin.get(); cin.get(); cin.get(); cin.get(); return 0; } if( old_x != x || old_y != y ){ FindPath( ex,ey,x,y ); } gotoxy( x,y ); cout << "P"; map[ey][ex] = '.'; gotoxy( ex, ey ); cout << "."; if( frame%speedmod == 0 && walk_queue.size() != 0 ){ ex = walk_queue.back().x; ey = walk_queue.back().y; walk_queue.pop_back(); } gotoxy( ex, ey ); cout << "M"; if( ex == x && ey == y ){ break; } gotoxy( 32, 18 ); gotoxy( 32, 1 ); cout << pts; Sleep( 100 ); frame++; }
Percobaanlebihlanjut • Pahamimasing-masingfungsidanbaris program, kemudianberiketerangan/comment di setiapbaris/pokokbesarprogramnya. Lakukandengatanda // (untuk 1 baris) atau /* isi comment */ utuklebihdari 1 baris. • Gantiposisi start MusuhPacMandalam 3 keadaan start yang berbeda • Jikasudahberhasil, cobagandakanmusuhpacmanmenjadi 4, sebagimanalayaknyapermainanPacMan. Sebarposisinyasaat start. Amati pergerakannyadalammengejar actor/PacMantersebut. • Analisadanjelaskanhasilpraktikumnya • Buatlaporan
Referensi • Birch, Chad (2010), Understanding Pac-Man Ghost Behaviour (http://gameinternals.com/post/2072558330/understanding-pac-man-ghost-behavior) • Pittman, jamey (2010), Pac-Man Dossier (http://home.comcast.net/~jpittman2/pacman/pacmandossier.html) • NugrohoChandra, Timotius (2010), AplikasiAlgoritma Greedy untukPergerakanMusuhpada Pac-Man, InstitutTeknologi Bandung, Bandung