Högskolan på Åland serienummer 2013:42. Informationsteknik. Mariehamn 2013 ISSN 1458-1531



Relevanta dokument
PROJEKTRAPPORT EDA095 NÄTVERKSPROGRAMMERI

Fyra i rad Javaprojekt inom TDDC32

FrontPage Express. Ämne: Datorkunskap (Internet) Handledare: Thomas Granhäll

Kortspel. Ett spel - tusen upplevelser

getsmart Grå Regler för:

Grundläggande programmering, STS 1, VT Sven Sandberg. Föreläsning 20

UPPGIFT 1 V75 FIGUR 1.

Allmänt om Pidro. Spelets uppbyggnad

getsmart Gul Regler för:

Handbok Officersskat. Martin Heni Eugene Trounev Granskare: Mike McBride Översättare: Stefan Asserhäll

Programmering A C# VT Ett kompendie över Programmering A (50p) i c# Stefan Fredriksson

Objektorientering i liten skala

Från Smart TV till Smartare upplevelse Av: Kim Huber och Connie Huanca

Digitalt lärande och programmering i klassrummet

Ungefär lika stora tal

Programmering. Den första datorn hette ENIAC.

Lathund till Publisher TEXT. Skriva text. Importera text. Infoga text. Dra och släpp

Appar vi arbetat med

Sidpanelen och gadgetar De är nya. De är smarta. Lär dig hur du använder dem.

Uppgift 1 ( Betyg 3 uppgift )

Att skriva på datorn

Grunder. Grafiktyper. Vektorgrafik

3. Välj den sprajt (bild) ni vill ha som fallande objekt, t ex en tårta, Cake. Klicka därefter på OK.

SLUTRAPPORT: TEXAS HOLDEM 4 FRIENDS

KURSMÅL WINDOWS STARTA KURSEN

Föreläsning 2. Operativsystem och programmering

Roboten. Sida 1 av 11

Gran Canaria - Arbetsbeskrivning knapplänkar (Mediator 8)

IT-körkort för språklärare. Modul 9: Rätta skrivuppgifter

Gränssnitt för FakeGranska. Lars Mattsson

Ett enkelt OCR-system

kl Tentaupplägg

Kravspecifikation. Sammanfattning. Fyra i rad Javaprojekt inom TDDC32. Version 2.0. Datum Dokumentnummer

Projekt Rapport. RaidPlanner. Jeanette Karlsson UD10

Internet. En enkel introduktion. Innehåll:

och Lär dig surfa på Internet Bilden nedan föreställer Södertälje kommuns hemsidans startsida Adressen till hemsidan

Implicita odds och omvända implicita odds

Objektorientering: Lagring och livstid

Föreläsning 3.1: Datastrukturer, en översikt

Dollar Street Beta Version 1.0 Manual

[SLUTRAPPORT: DRAWPIXLZ (ANDROID-APP)] Slutrapport. Författare: Zlatko Ladan. Program: Utvecklare av Digitala Tjänster 180P

Pottstorleksfilosofin ett exempel

Appar vi arbetat med. ipad projekt 2013 appar vi jobbat med. Nina Lundell Sida "1

Instruktioner. Innehåll: 1. Vad är Kimsoft Control (SIDA 2) 3. Hem (SIDA 2)

Copema Supertoto, manual

Vanliga frågor för VoiceXpress

Introduktion till programmering, hösten 2011

Lathund Claro Read Plus

Win95/98 Nätverks Kompendium. av DRIFTGRUPPEN

Datatal Flexi Presentity

Programmeringsuppgift Game of Life

TDIU Regler

Regler för: - Räkna med sedlar og mynt!

Orienteringsövningar. Oskar Andrén Värmlands Orienteringsförbund

Programmering B med Visual C

Välkommen till Ipad för nybörjare

Agenda. Objektorienterad programmering Föreläsning 13

6. Nu skall vi ställa in vad som skall hända när man klickar på knappen samt att markören skall ändra sig till en hand när markören är på knappen.

Komma igång med Qlikview

Programmering eller Datalogiskt tänkande

Alla datorprogram har en sak gemensam; alla processerar indata för att producera något slags resultat, utdata.

Handbok Dela Skrivbord. Brad Hards Översättare: Stefan Asserhäll

getsmart Lila Regler för:

Introduktion till Datalogi DD1339. Föreläsning 2 22 sept 2014

Nyheterna i Visma Tendsign 4.0

Laboration i datateknik

ONEDRIVE ÖVERBLICK Vad är OneDrive?... 2 Molnet?... 2 Två typer av OneDrive... 2 Hitta sin OneDrive för företag... 3

Talsystem Teori. Vad är talsystem? Av Johan Johansson

1(15) Bilaga 1. Av Projekt Neuronnätverk, ABB Industrigymnasium, Västerås Vt-05

Objektorientering: Lagring, räckvidd och livstid

Instruktioner till övningen som börjar på nästa sida

Snabbstartguide för McAfee VirusScan Plus

Programmeringsteknik med C och Matlab

ANVÄNDARBESKRIVNING FÖR PERSONAL

7-2 Sammansatta händelser.

«Sida 2 av 4 Till kursens framsida Sida 4 av 4»

Regler för: getsmart Grön

FIRSTCLASS. Innehåll:

Kortdokumentation. Avancerade Wordfunktioner

Att skriva till och läsa från terminalfönstret

JavaScript del 5 Funktioner

Allta bilder du ritar med verktygen i verktygspanelen eller importerar är grafik.

PROGRAMMERINGSTEKNIK TIN212

UB:s sö ktjä nst - Söka artiklar och annan litteratur

Skärmtangentbordet som är enkelt att använda både med mus, touchskärmar och interaktiva whiteboards

Mitt hus och jag steg för steg instruktioner

TDIU01 - Programmering i C++, grundkurs

Handbok Othello. Clay Pradarits Utvecklare: Mario Weilguni Granskare: Lauri Watts Översättare: Stefan Asserhäll

Säkerhetsinställningar, websolen. Innehåll

Kapitel 1 Introduktion

Generell säkerhet. Loggning - Hur mycket ska man logga? Inloggningsrutinerna i Unix. Loggning fortsättning

Ikonen för ett Microsoft Word-dokument.

Att använda talsyntes i en lässituation.

Snabbguide till Cinahl

Extramaterial till Matematik Y

Programmering. Scratch - grundövningar

BRIDGE MASTER 2000 SCANDINAVIA av Fred Gitelman

SkanRead hjälp. SkanRead 2.0. Elevdata AB

Miljön i Windows Vista

Transkript:

Nätpokerboten Mats Enqvist Högskolan på Åland serienummer 2013:42 Informationsteknik Mariehamn 2013 ISSN 1458-1531 Mariehamn 2009

Examensarbete Högskolan på Åland Utbildningsprogram: Författare: Arbetets namn: Handledare: Uppdragsgivare: - Informationsteknik Mats Enqvist Nätpokerboten Agneta Eriksson-Granskog Abstrakt: Syftet med denna uppsats är att undersöka och utveckla olika metoder för att få en fungerande online pokerbot. En bot är ett automatiserat program som utför vad den blivit programmerad till att göra, utan att en användare behöver styra eller övervaka programmet. Även om det är en pokerbot som jag valt att fokusera på så är det meningen att uppsatsen skall ge en idé om hur man kunde automatisera andra program och inte bara ett pokerspel. Nyckelord (sökord): Robot, automation, minnesläsning, poker Högskolans serienummer: ISSN: Språk: Sidantal: 2013:42 1458-1531 Svenska 27 Inlämningsdatum: Presentationsdatum: Datum för godkännande: 27.11.2013 17.5.2013 27.11.2013

Degree Thesis Högskolanpå Åland / Åland University of Applied Sciences Study program: Author: Title: Academic Supervisor: Technical Supervisor: - Information Technology Mats Enqvist Online poker bot Agneta Eriksson-Granskog Abstract: The purpose of this essay is to examine different methods to develop an online poker bot. A bot is a automated program that does what it has been programmed to do, without the need of control or supervision by the user. Even if the focus in this essay is poker, the point is to give an idea of how to automate other programs and not only a online poker game. Key words: Robot, automation, memory reading, poker Serial number: ISSN: Language: Number of pages: 2013:42 1458-1531 Swedish 27 Handed in: Date of presentation: Approved on: 27.11.2013 17.5.2013 27.11.2013

INNEHÅLL 1. Inledning... 3 1.1. Motiv... 3 1.2. Syfte... 3 1.3. Metod... 3 1.4. Avgränsningar... 4 2. Spelet Texas hold'em... 4 3. Struktur och funktionalitet för pokerboten... 9 4. Åtkomst av data... 12 4.1. Skärmskrapning... 12 4.1.1. Exempel på skärmskrapning i Texas hold'em... 14 4.2. Minnesläsning... 15 4.2.1. Minnesläsning i Java... 16 4.2.2. Exempel: läsning av de gemensamma korten i pokerspelet... 17 4.3. Val av dataåtkomstmetod... 20 5. Kommunikation mot pokerklient... 21 6. Undvika upptäckt... 24 6.1. Metoder för att avslöja pokerbotar... 24 6.2. Speltid... 24 6.3. Timings... 24 6.4. Spionprogram i pokerklienten... 24 6.5. CAPTCHA... 25 6.6. Spelmönster... 25 7. Slutord... 26 8. Litteraturförteckning... 27

1. Inledning 1.1. Motiv Valet av en pokerbot är en kombination av flera intressen. Automation är ett intressant ämne och det är något som eftersträvas inom IT-branschen men även inom andra områden. Poker är något av ett fritidsintresse för mig och att utveckla en bot som automatiskt spelar poker kändes som en bra utmaning. 1.2. Syfte Syftet med detta arbete är att utveckla och dokumentera en pokerbot. En stor del av arbetet är att undersöka och testa olika metoder för att få boten att fungera. Även om jag valt att fokusera på en pokerbot är det meningen att uppsatsen skall ge en idé om hur man kan tillämpa dessa metoder och automatisera inom andra områden lika väl. 1.3. Metod Som programmeringsspråk kommer Java tillsammans med editorn NetBeans att användas. Valet kändes naturligt då jag har erfarenhet av Java och NetBeans men främst på grund av vissa inbyggda funktioner i Java, till exempel Robotklassen. Robotklassen innehåller funktionalitet såsom läsning av pixlar och styrning av mus och tangentbord som annars skulle vara tvunget att byggas upp från grunden eller lånas från externa bibliotek. Arbetssättet bygger på att undersöka teoretiskt, implementera och testa de olika metoderna som kan användas för att få funktionaliteten en pokerbot behöver för att fungera. Som litteratur används i första hand internet samt böcker inom området. 3

1.4. Avgränsningar På grund av projektets omfattning har vissa avgränsningar gjorts. En pokerbot kan göras på en hel del olika sätt och jag har valt att fokusera på gränssnittet från boten till omvärlden. Med andra ord hur boten tar reda på vad som händer i pokerprogrammet och hur den skall kommunicera tillbaka. En enkel pokerintelligens kommer att utvecklas för att testa boten i sin helhet men det är inget som kommer att nämnas i någon större utsträckning. Artificiell pokerintelligens är ett välstuderat området, teorier och studier kan hittas i mängder på nätet och böcker så jag valde därför att inte behandla det i uppsatsen. En del pokersidor förbjuder användningen av pokerbotar och därför kommer teorier för hur man undviker upptäckt att diskuteras och ligga i baktanke under utvecklingen av boten. Den här uppsatsen kommer inte ta någon ställning till användning av botar på sidor som förbjuder det. Eftersom det finns en hel del olika typer av pokerspel och ännu fler aktörer av online poker har jag valt att fokusera på ett specifikt spel, Texas hold'em, på en specifik pokersida. Att göra en pokerbot som kan spela olika spel på olika sidor skulle kräva oerhörda mängder av arbete. Men detta extra arbete skulle inte tillföra det här arbetet mycket eftersom det egentligen bara är små variationer som tas i beaktande från fall till fall och i grunden fungerar en pokerbot likadant oavsett spel eller vilken sida som används. 2. Spelet Texas hold'em För att förstå hur en pokerbot opererar och vad den skall klara av behövs lite pokerkunskap. Det finns flera olika pokerspel och ett av de populärare är Texas Hold'em (Glimne, 2005). Texas Hold'em är ursprungligen ett bordsspel men online versionen är i princip samma sak. Spelet finns i några varianter men alla fungerar på liknande sätt. Figur 1 visar en illustration av Texas hold'em. 4

Figur 1 Texas hold'em (Drm0hr, 2012) Texas Hold'em kan spelas med två till tio spelare. Spelet körs i omgångar, varje omgång börjar med att varje spelare tilldelas två kort. Dessa två kort kallas hålkort och spelarna får bara se sina egna kort. Dealerknappen (button i figuren) roteras medurs efter varje omgång. Spelarna direkt efter knappen måste betala en liten mörk och stor mörk (Small Blind och Big Blind i figuren). Spelaren efter stor mörk är alltid först att agera. Det finns fyra drag man kan göra: 1. Lägga sig. Detta gör man oftast om man har dåliga kort och inte vill vara med i omgången. 2. Syna. För att vara med i spelet måste man syna, alltså betala lika mycket som nuvarande insats ligger på. Om ingen har höjt insatsen är det stor mörk man måste betala. 3. Höja. Gillar man sina kort kan man höja insatsen. Då måste alla spelare som vill vara med betala samma insats. 4. Check. Om ingen har höjt insatsen kan t.ex. stor mörk välja att checka eftersom hon eller han redan betalat insatsen. När alla spelare antingen lagt sig eller synat kommer de första tre gemensamma korten. Dessa tre kort delas synliga och alla kan använda dessa kort för att bilda en pokerhand. En till runda av antingen checkar, höjningar, syn och läggningar görs och nästa 5

gemensamma kort delas ut. Ytterligare en omgång av samma val görs och sista kortet delas ut. Nu sker den sista omgången där man kan höja, checka, syna eller lägga sig. Om flera spelare är med i slutet visas korten och vinnaren avgörs. Vinnaren är den som har den starkaste femkortshanden av de fem synliga och de två egna hålkorten. Spelet behöver inte alltid komma så långt som till sista kortet och kan avgöras genom att få alla andra spelare att lägga sig. Då vinner man potten utan att behöva visa sina kort. Texas Hold'em fungerar likadant online och spelas oftast med ett pokerprogram som laddas ner från pokersidan man valt att spela på. Det grafiska gränssnittet i pokerklienten visar all information som finns tillgänglig och boten behöver läsa precis samma information som en person läser från pokerfönstret. Figur 2 nedan visar ett typiskt pokerfönster i en pokerklient. Vad en pokerbot behöver läsa från klienten beror på hur komplex den görs. En bot som bara lägger sig hela tiden behöver bara kolla när läggningsknappen går att trycka på. En mer avancerad bot vill så klart veta mycket mer än så. Följande information måste kunna läsas från pokerklienten: - Hålkorten och de gemensamma korten på bordet - Positionen av knappen - Hur många spelare som finns totalt på bordet - Hur många av dessa spelare som fortfarande är med i spelet - Potten (totala summan av insatserna) - Motståndarbeteende 6

Figur 2 Illustration av ett pokerfönster i en nätpokerklient Hålkorten (eller starthanden), de två korten som delas ut i början av rundan, måste läsas för att avgöra om det är värt att alls delta i omgången. Vad som är bra starthänder kan diskuteras men vissa händer har helt enkelt lägre chans att få en bättre hand än motståndarna. Positionen har en viktig roll i Texas Hold'em. Dealerknappens position avgör vem som är först att agera. Att agera sist är en stor fördel eftersom man får se vad alla andra gör före man själv gör sitt val. Antalet spelare som är med har en matematisk inverkan, ju fler spelare som är med ju större är chansen att någon har en bättre hand, vilket också påverkar hur spelet spelas. Om pokerboten inte är programmerad med strategier för varierat antal motståndare måste pokerboten byta bord eftersom strategier för ett spel mot en eller två motståndare skiljer sig avsevärt jämfört med ett fullt bord. 7

Även den totala pottstorleken har en matematiskt inverkan på spelet. Detta kan kanske enklast förklaras med ett exempel: Om den totala potten är 20 och någon höjer med ytterligare 20 måste 50% av den totala pottstorleken betalas för att fortsätta i spelet, om chansen att vinna är mindre än 50% är det då inte värt att fortsätta eftersom det helt enkelt inte kommer att vara lönsamt i längden att spela. Att följa med vem som synar och vem som höjer och samtidigt studera strukturen på de gemensamma korten kan ge ledtrådar om vilka kort dessa spelare sitter på, det är viktigt att studera spelarbeteende ifall de kan ge ledtrådar om deras handstyrka. För att få all denna information från pokerklienten och för att kommunicera tillbaka till klienten finns det en del möjliga metoder. Det är just dessa metoder som kommer att undersökas närmare i kommande kapitel. Vinstpotentialen för en pokerbot finns på grund av att en dator kan räkna exakta odds baserat på kort och annan information och göra matematiskt korrekta val. En vanlig mänsklig spelare kan eller hinner inte räkna ut samma information. Även om vinstmarginalerna kan vara små för en bot så blir den aldrig trött eller uttråkad och kan spela i all evighet. 8

3. Struktur och funktionalitet för pokerboten Körningen av en pokerbot kan beskrivas med tre faser: 1. Inläsning 2. Beräkning 3. Utförande Figur 3 visar ett tänkbart flödesschema för dessa tre faser i pokerboten. Figur 3 Pokerbotens tre faser 9

Inläsningsfasen består av att samla in all information som behövs för att boten skall kunna räkna ut korrekta odds. Ju mer information som kan samlas från pokerspelet desto bättre beslut kan räknas ut. Det finns en mängd olika metoder för att samla denna data och några av dessa kommer att undersökas närmare. Beräkningsfasen handlar om att räkna ut odds och därmed rätt beslut i pokerspelet. Utförandefasen handlar om att utföra beslutet i pokerklienten. Detta består av att göra drag i själva spelet men en helautonom bot måste också klara av att stänga och öppna nya bord. Eftersom en stor del av arbetet bygger på att prova olika metoder behövs ett modulärt angreppssätt. Målet är att lätt kunna byta ut en metod mot en annan utan att behöva koda om stora delar av programmet. Klassdiagrammet i figur 4 visar ett förslag på hur en pokerbot kunde byggas för att tillfredställa dessa krav. Det hela fungerar genom att skapa ett objekt av typen bot. Bot objektet använder sig av gränssnitten Gatherer och OutputHandler för att agera med pokerklienten. Vad t.ex. Gathererobjektet är av för typ spelar ingen roll, meningen är att den kan bytas ut mot valfri metod förutsatt att den implementerar gränssnittet. På så sätt kan man växla mellan t.ex. minnesläsning eller skärmskrapning. För mer information om objekt och gränssnitt i Java se (Niemeyer & Knudsen, 2005). Pokerklienter tillåter ofta att flera bord öppnas och spelas på samtidigt. För att maximera vinsten borde då också boten klara av flera bord på samma gång. För att göra detta skapas flera botobjekt, varje bot kör sin egen tråd och sköter sitt eget bord. En viss kommunikation krävs mellan botobjekten så de inte försöker göra drag i pokerklienten för snabbt eller samtidigt. Detta kan lösas genom att varje bot kollar med ett gemensamt tidsobjekt och ser till att tillräckligt lång tid har passerat från föregående drag. 10

Figur 4 Klassdiagram för pokerboten 11

4. Åtkomst av data 4.1. Skärmskrapning En vanlig metod för botar att samla information är skärmskrapning (eng. screen scraping) (Data Scraping, Wikipedia, 2013b). Detta innefattar att tolka det grafiska gränssnittet som presenteras av applikationen. Skärmskrapning består av två steg: 1) Hitta delarna av gränssnittet som är intressanta 2) Tolka det grafiska gränssnittet till data som boten kan hantera Det första steget är relativt enkelt i ett pokerspel eftersom elementen i spelet är helt statiska och inte byter position. Koordinater för viktiga positioner kan skrivas i t.ex. en XML-fil för att separera statiska variabler från programlogik. Om pokerboten spelar på fler bord samtidigt blir det dock väldigt många koordinater att hålla reda på, om det finns tio koordinater av intresse på ett bord och pokerboten spelar på nio bord samtidigt blir det 90 olika koordinater. För att lösa detta kan ett system av referenspunkter användas. Koordinaterna av intresse sparas utifrån en punkt på spelbordet, t.ex. övre hörnet till vänster, på så sätt behövs bara en koordinat för detta hörn på varje spelbord för att räkna ut resten av koordinaterna. Det andra steget innebär att tolka gränssnittet till rätt information. Detta består av att läsa enstaka pixlar men siffror och bokstäver måste också tolkas ur gränssnittet. Bildanalys av text kallas OCR (Optical Character Recognition) (Nimcomsoft). En bra implementerad optisk teckenläsare klarar av olika typer fonter och storlek på texten. Eftersom en kortlek endast består av siffrorna 2-10 och bokstäverna J,Q,K,A kanske det inte är nödvändigt att implementera en fullständig textigenkänningsalgoritm vid utveckling av en pokerbot. En naivare textläsare som bara klarar av en exakt teckenstorlek, ett teckensnitt och några få tecken skulle spara en hel del arbete om man inte planerar att använda pokerboten på många olika pokersidor. En primitiv optisk teckenläsare kunde implementeras på följande sätt: 12

Naiv metod 1) Räkna antalet pixlar varje tecken består av, spara värdena i en tabell för senare jämförelse. Naiv metod 2) Spara en bild på varje tecken som finns för att sedan jämföra med exakt bildmatchning. Dessa metoder fungerar naturligtvis bara under rätt omständigheter men de är enklare att implementera än en mer avancerad textläsningsalgoritm. Oavsett vilken metod som används så måste pixlar läsas från skärmen vilket är enkelt i Java med det inbyggda biblioteket jawa.awt.robot (Oracle, 2010). Kodexemplet nedan visar hur färgen på en bestämd pixel kan fås. Koordinaterna (x, y) anger vilken pixel som skall läsas. Ur Color-objektet kan RBG-värden (mängden rött, blått och grönt) hämtas för att kolla vilken färg pixeln är. import java.awt.robot; Robot robot = new Robot(); Color c = robot.getpixelcolor(x, y); Färgerna anges som vanligt med mängden rött, blått och grönt på en skala från 0-255. En av de största fördelarna med läsning av pixlar är att det inte finns någon direkt kommunikation till pokerklienten. Pokerboten är bara ett program som läser vad som råkar finns på skärmen och för ingen direkt kommunikation med pokerklienten. 13

4.1.1. Exempel på skärmskrapning i Texas hold'em Dealerknappen kan endast finnas på tio olika positioner, dessa tio positioner är alltid samma och det är då enkelt att kolla om pixeln på knappositionen består av bakgrundsfärgen på bordet eller om den har en annan färg, vilket då tolkas som att knappen just då ligger där. Motståndarantal läses på liknande sätt. Om en motståndare är med eller inte representeras av två kort i spelet bredvid spelarens ikon. Om kortets färger inte kan hittas bredvid spelarens ikon, är han inte med i omgången. Spelkort kräver att två delar tolkas, valören och färgen på kortet. Färgen kan avgöras genom att kolla symbolen på kortet. Till skillnad från traditionella kortlekar har pokerklienter ofta valet att representera de fyra olika färgerna hjärter, klöver, spader och ruter med fyra olika färger istället för endast rött och svart. För att avgöra kortets färg kan RGB-värdena studeras: Hjärter (rött): Högt värde på rött, lågt på blått och grönt Ruter (blått): Högt värde på blått, lågt på rött och grönt Spader (svart): Lågt värde på samtliga färger Klöver (grönt): Högt värde på blått och grönt, lågt på rött Spelkortets valör eller rank skrivs med siffrorna 2 till 10 och J, Q, K, A och dessa måste urskiljas ifrån varandra med hjälp av optiskt teckenläsning. Potten representeras av ett par siffror och dessa måste också läses med optiskt teckenläsning. 14

4.2. Minnesläsning En alternativ metod till skärmskrapning är minnesläsning. Arbetsminnet eller RAMminnet är en viktig komponent i en dator, alla program som körs på en dator har ett allokerat minnesområde i RAM-minnet (Wikipedia, 2013d). I detta minnesområde lagras temporära datavariabler som används av program när de körs på datorn. Dessa variabler kan läsas och användas av en bot. Det finns en del utmaningar med minnesläsning: - Hur representeras data i minnet? - Var i minnet finns datan? Data kan lagras på många olika sätt och i olika variabeltyper och utan kunskap om programmets inre struktur kan det vara svårt att veta exakt hur data lagras. Om t.ex. ett datum eftersöks i minnet, lagras då datumet som en sträng, ett par heltal eller någonting helt annat? Detta beror helt på hur programmeraren har valt att göra programmet och ibland kan det vara svårt att veta hur specifik funktionalitet representeras i minnet. Eftersom man alltid inte vet exakt vad man letar efter är det också svårt att hitta det. Att manuellt söka genom minnet är inte heller praktiskt då tusentals rader av binär data inte är det lättaste att försöka förstå. För att få ett begrepp om hur minnet ser ut kan olika minnesläsningsprogram användas. Cheat Engine är ett sådant program (Cheat Engine). Med Cheat Engine kan minnesområdet för ett visst program öppnas, läsas och sökas igenom. Öppnas ordbehandlingsprogrammet jag använder i Cheat Engine kan vi hitta texten jag just nu sitter och skriver (se figur 4). Figur 5 En bit av minnet som används av ett ordbehandlingsprogram. 15

4.2.1. Minnesläsning i Java Minnesläsning är något som inte finns inbyggt i Java. För att använda Windows specifika funktioner såsom minnesläsning måste externa bibliotek användas. Med biblioteket JNA, Java Native Access, kan funktioner anropas som inte annars finns tillgängliga i Java (Wikipedia, 2013c). För att läsa minnet för ett program måste dess minnesområde först öppnas för att sedan läsas, detta görs med två funktioner, OpenProcess (Microsoft, 2012a) och ReadProcessMemory (Microsoft, 2012b). HANDLE WINAPI OpenProcess( _In_ DWORD dwdesiredaccess, _In_ BOOL binherithandle, _In_ DWORD dwprocessid ); BOOL WINAPI ReadProcessMemory( _In_ HANDLE hprocess, _In_ LPCVOID lpbaseaddress, _Out_ LPVOID lpbuffer, _In_ SIZE_T nsize, _Out_ SIZE_T *lpnumberofbytesread ); parameterförklaring: dwdesiredaccess binherithandle dwprocessid hprocess lpbaseaddress lpbuffer nsize lpnumberofbytesread Behörighetsnivå, t.ex. läsa eller skriva Om värdet är sant ärvs processens handtag Alla processer identifieras av ett ID Pekare till processen som öppnats Adressen som skall läsas ifrån I buffern sparas data som läses Storlek på buffer Pekare till antalet bytes som läses 16

4.2.2. Exempel: läsning av de gemensamma korten i pokerspelet För att koda ett användbart minnesläsningsprogram måste vi först bekanta oss med pokerklienten med hjälp av Cheat Engine. Precis som vilket datorprogram som helst lagras data i variabler i pokerklienten. Det första steget är att ta reda på exakt vilka minnesadresser innehåller informationen som eftersöks. För att hitta det vi söker efter i pokerklienten måste vi förstå var och hur detta lagras i minnet. Att manuellt leta igenom minnet efter t.ex. ett kort i spelet skulle inte vara möjligt, det finns miljontals bytes och det skulle ta alltför lång tid. Det fina med Cheat Engine är att vi kan söka genom hela minnet efter ett visst värde. Om vi t.ex. vill hitta minnesadressen för det första gemensamma kortet på bordet kan vi med en specifik sökteknik hitta minnesadressen för kortet. Detta kort lagras högst antagligen någonstans i minnet och även om värdet på detta kort förändras förblir platsen densamma. Med lite tur lagras kortets valör direkt med motsvarande siffra i minnet, med andra ord, valören för klöver två lagras som en tvåa, ruter sju lagras med en sjua, etc. Knepet vi nu måste använda är att söka i föregående sökresultat: Om vi ser i pokerklienten att kortet vi letar efter just nu är ett kort med valören 7 kan vi söka igenom hela minnet för pokerklienten efter siffran 7. Högst antagligen kommer vi få tusentals med träffar, men det är okej eftersom vi sparar alla adresser som hade värdet 7 till nästa sökning. När kortet i spelet sedan ändras, säg till ett kort med valören 4, kan vi nu söka efter värdet 4. När vi nu söker bland föregående resultat har kanske 500 av dessa råkat få värdet 4. Nästa gång kortet ändras kanske vi får 100 resultat. Fortsätter vi så här och om allt går rätt finns det bara en adress kvar i slutet. När man bekräftat att värdet för denna minnesadress ändras samtidigt och till rätt värde som det ändras i pokerspelet kan man anta att detta är just den adressen som innehåller vad man letar efter. När vi nu hittat adressen kan vi med hjälp av Cheat Engine studera närliggande minnesområde (figur 6) för att se om vi kan hitta någonting annat. Figur 6 Community kortens valörer markerade med blått. 17

Det första kortet har adressen 05995954, kortet representeras av talen 4 och 64. Kortets valör visas med en 4:a och färgen med 64 (64 kan översättas till 'd' med en ASCIItabell, 'd' är kort för diamonds, ruter på engelska). Med andra ord första kortet är en fyra med färgen ruter. Även fast vi endast sökte efter det första kortet kan vi se att vi också har hittat de fyra andra korten. Det andra kortet representeras av C och 73, tredje av 3 och 63 o.s.v. Vi kan också se att korten ligger med jämna mellanrum ifrån varandra, vilket betyder om vi hittar det första kortet, kan vi hitta de andra. Vi har nu hittat fem adresser för de fem korten som ligger på bordet i spelet. Tyvärr kan inte dessa adresser användas rakt av. När pokerklienten startas om finns det ingen garanti att samma minnesområde används, det är med högsta sannolikhet helt nya adresser. Vi kan inte heller konstruera vår bot att använda ovanstående sökmetod, boten vet ju inte vilka kort den skall söka efter. Utmaningen med minnesläsning är att pokerboten själv ska dynamiskt hitta de minnesadresser den behöver, utan att användaren av boten behöver säga åt den var den skall leta. Det hela handlar om att hitta något som identifierar vilka minnesadresser som skall läsas. Detta kan vara ett mönster, på sättet informationen är lagrad eller något som unikt som identifierar rätt minnesområde. I det här fallet så kommer det alltid samma unika sekvens med bytes före själva korten. Vad denna sekvens av bytes är, eller varför den finns där är inte så viktigt, det viktiga är att den alltid förekommer på endast ett ställe, med ett precis antal bytes före platsen med korten. Så för att dynamiskt hitta korten behöver vi bara hitta sekvensen av bytes som har markerats i figur 7. Figur 7 Unik sekvens av bytes markerat i orange, efter denna sekvens kommer de fem sökta korten. 18

Öppnas fler pokerbord i pokerklienten skapas också denna sekvens av bytes på lika många ställen. För att pokerboten skall klara av att spela på fler bord samtidigt måste rätt kort kopplas till rätt bord. Detta kan lösas genom att öppna ett bord i taget. Efter att det första bordet har öppnats, leta fram adressen för det första bordet. Vartefter nya bord öppnas, hoppa över tidigare bords adresser så dessa inte beaktas i nya sökningar. På så sätt kan rätt minnesadress kopplas till rätt pokerbord. Förstås, vissa delar av pokerklienten kan vara svåra att hitta i minnet om man inte känner till dess inre struktur. Det kan vara svårt att veta vad man ska leta efter, veta hur allting representeras i minnet eftersom en viss funktionalitet kan programmeras på så många olika sätt. 19

4.3. Val av dataåtkomstmetod Skärmskrapning och minnesläsning har båda för- och nackdelar, vilken metod som borde användas beror på pokerklienten man har valt. Skärmskrapning fungerar väldigt bra för enklare läsning såsom position eller antal motståndare i pokerspelet, medans läsning av siffror och bokstäver kräver mer arbete, speciellt om pokerklientens grafiska gränssnitt ofta förändras i programuppdateringar. T.ex. om koordinater för relevant data måste uppdateras eller om teckenstorlek eller teckensnitt ändras kanske hela textigenkänningsalgoritmen måste programmeras om. Om så är fallet fungerar minnesläsning kanske bättre då det är mindre sannolik att inre programförändringar sker. Med andra ord, skärmskrapning fungerar bättre till enklare grejer som inte kräver mycket underhåll ifall gränssnittet skulle ändras och minnesläsning fungerar bättre för läsning av exakt data som siffror och bokstäver. Även fast det är fullt möjligt att exklusivt använda endast en metod kanske det är mindre arbete för en programmerare att använda en kombination av både minnesläsning och skärmskrapning. Förstås finns det även fler metoder än endast minnesläsning och skärmskrapning. Den enklaste formen skulle vara att läsa och tolka en logfil som pokerklienter oftast har. En logfil innehåller information om kort och andra händelser i pokerklienten. Logfilerna är dock ofta inte tillräckligt bra för att räcka för en mer komplicerad bot. De innehåller inte alltid all information som behövs eller så uppdateras de inte i real tid. En orsak till detta är antagligen för att just stoppa botar från att enkelt kunna läsa all information som behövs. Eftersom spelet körs online och mot en server måste information om kort, pott etc. komma utifrån via nätet. Denna nätverkstrafik kan i teorin avlyssnas när den kommer in till pokerklienten. Denna nätverkstrafik kan dock vara krypterad men pokerklienter vars kommunikation inte är kunde detta vara en möjlig metod. I slutändan beror valet av metod på pokerklienten, den metod som fungerar bäst eller som är enklast att implementera på just den pokerklienten. 20

5. Kommunikation mot pokerklient När pokerboten väl samlat in all nödvändig information, bearbetat och gjort ett val måste valet också ageras. Boten behöver precis som en människa trycka på rätt knappar i pokerklienten. Det kanske enklaste sättet är att simulera rörelser och tryck med musen. Att styra musen är bekvämt i Java med hjälp av det inbyggda bibliotek, java.awt.robot. För att flytta på muspekaren krävs ett objekt av typen Robot och ett funktionsanrop. import java.awt.robot; import java.awt.event.inputevent; Robot robot = new Robot(); robot.mousemove(150, 200); Denna kod är allt som behövs i Java för att flytta musen till t.ex. pixel positionen (150, 200). För att sedan trycka ned och släppa musknappen för att simulera ett klick behövs följande kod: robot.mousepress(inputevent.button1_mask); robot.mouserelease(inputevent.button1_mask); Eftersom knapparna alltid ligger på samma ställe är det relativt enkelt att skriva ett par funktioner för att lägga sig, syna eller höja. Det går också att läsa var musen befinner sig, var den gör klick. Det är då inte heller helt orimligt att också pokerklienter läser musdata för att leta efter omänskligt beteende, för att stoppa botar. Det vore väldigt omänskligt att alltid trycka på exakt samma pixel varje gång så därför behövs ett mer slumpmässigt beteende. Eftersom knapparna har en viss storlek kan en koordinat slumpas fram som ligger nånstans inom knappens omkrets. Det är svårt att veta exakt hur olika pokerklienter analyserar musbeteende. För att vara på den säkra sidan borde också muskoordinater mellan knapparna simuleras istället för att musen konstant skulle hoppa från knapp till knapp. Att gå från punkt A till B i ett rakt sträck räcker knappast då en människa ofta flyttar musen i någon slags bågformad rörelse. 21

En metod att få en kurva mellan två punkter är att använda Bézierkurvan (Bézier curve, Wikipedia, 2013a). Formeln nedan är en kubisk Béizer. [x,y]=(1 t)3p0+3(1 t)2tp1+3(1 t)t2p2+t3p3 P0 och P3 är start och slutpunkten på kurvan. P1 och P2 bestämmer hur kurvan kommer att se ut beroende på hur de ligger i förhållande till P0 och P3. Figur 3 visar hur en kubisk Bézier fungerar. Genom att slumpa fram koordinaterna P1 och P2 (de gula punkterna i figur 3) kan vi få hyfsat realistiska och slumpmässiga kurvor för musen att följa. Figur 8 Kubisk Bézier (Tulleken, 2011) Människor klarar av korta avstånd utan större felmarginal men vid längre avstånd så missar vi mera när vi går från en punkt till en annan med musen. Detta är enkelt att 22

efterlikna om de slumpmässiga punkterna placeras baserat på hur lång sträcka musen måste flyttas. Ju längre bort de gula punkterna är från de orangea, ju större kurva kommer vi att få. Resultatet blir en mer mänsklig rörelse (figur 10) istället för att flytta musen i raka sträck. I figuren ser vi att båda metoderna träffar slumpmässigt inom knappen men med Bézier fås en mer mänsklig för själva rörelsen mellan knapp till knapp. Figur 9 Jämförelse av Bézier (övre delen av figuren) och att gå raka sträck mellan knappar 23

6. Undvika upptäckt 6.1. Metoder för att avslöja pokerbotar Det finns olika metoder för att avslöja pokerbotar men det är svårt att säga exakt vad som används av pokersidorna. En metod är bara effektiv så länge den hålls hemlig eftersom annars skulle ju botutvecklare göra allt för att kringgå metoderna. Nedan följer tänkbara metoder och hur dessa kan undvikas. 6.2. Speltid En av de kanske mest uppenbara metoderna är att titta på speltid för en spelare. Om en spelare sitter och spelar hela tiden, dag ut, dag in, väcker det nog varningsflaggor i systemet, och denne spelare kan sedan granskas noggrannare för att avgöra om det är en bot som spelar. Det gäller då helt enkelt att begränsa spelandet till mänskliga mängder så att boten inte körs hela tiden. Boten borde också ta pauser, även om det är mycket möjligt att spela t.ex. 12 timmar per dag är det nog ytterst svårt att göra det utan pauser i spelandet. En lösning skulle kunna innefatta en schemaläggare som kör boten på slumpmässiga intervall. 6.3. Timings En bot får inte utföra beslut för snabbt för det är knappast troligt att en människa skulle utföra knapptryck på hundradelar och fortfarande spela med vinst. Även om en dator har snabb beräkningsförmåga måste boten vänta tillräckligt länge mellan varje kommando den skickar till pokerklienten. Den måste också vänta slumpmässig tid så väntetiden inte blir samma för varje drag boten gör. Väntetiden mellan varje drag borde resultera en minimum tid plus en slumpmässig del. 6.4. Spionprogram i pokerklienten Pokerklienter kan innehålla spionprogram som letar efter egenskaper för kända pokerbotar genom att granska processer som körs på användarens dator, t.ex. Pokerstars nämner detta i deras användaravtal (Pokerstars, 2013). Kända pokerbotar upptäcks genom att leta efter namn på processen eller söka efter processer med samma storlek som kända botar. Fördelen med att utveckla sin egen bot är att den är unik från andra pokerbotar och kan inte upptäckas rakt av så länge den inte öppet distribueras. 24

6.5. CAPTCHA Captcha (Completely Automated Public Turing test to tell Computers and Humans Apart) har länge använts för att stoppa botar på internet och det är logiskt att använda dessa för att bekämpa pokerbotar. Problemet med Captcha för en bot är att först upptäcka att en ruta med en förfrågan dykt upp och sedan att skriva in rätt kod. Även om Captcha har knäckts är det en ganska svår uppgift. Istället för att försöka knäcka Captcha kunde en skärmdump tas och skickas till användarens smarttelefon där denne kan fjärrstyra pokerprogrammet och fylla i åt boten. Figur 10 Captcha, en metod att stoppa botar 6.6. Spelmönster Om en spelare har blivit misstänkt för användningen av en pokerbot men direkta bevis inte är tillräckliga kan spelmönster studeras. En pokerbot programmeras ofta att klara av specifika situationer på ett specifikt sätt och spelmönster uppstår eftersom boten alltid spelar efter programmerade regler. Även vid väldigt regelbaserat spel från mänskliga spelare uppstår variationer på grund av t.ex. misstag eller magkänsla som får spelare att avvika från sin nitiska strategi. För att få in ett mer slumpmässigt spelmönster måste pokerboten programmeras med t.ex. slumpmässiga bluffar i spelet för att bryta eventuella mönster. 25

7. Slutord Att bygga en pokerbot visade sig vara ett gigantiskt projekt. Fördelarna med att utveckla en egen bot är stora men det kräver också mycket arbete. Genom att själv bygga en bot har jag också fått en förståelse hur botar kan stoppas, eller åtminstone försvåra arbetet för botutvecklare. Utvecklingen i Java tillsammans med NetBeans har fungerat utmärkt, trots att minnesläsningen krävde ett externt bibliotek. Andra programmeringsspråk kanske hade fungerat smidigare för just minnesläsningsdelen men att programmera en bot i Java är fullt möjligt. Genom att avgränsa mig till kommunikationen mellan pokerboten och pokerklienten har jag kunnat undersöka och även implementera mina valda metoder noggrant, detta hade inte varit möjligt om pokerintelligensen också hade behandlats, då det är ett helt ämne i sig. Pokerintelligensen som inte har behandlats i detta arbete skulle vara nästa steg i utvecklingen av pokerboten. Förhoppningsvis har denna uppsats gett en liten bild över vad som krävs för att utveckla en pokerbot men också hur tekniker som minnesläsning, skärmskrapning och styrning av mus kan användas för att automatisera andra program och spel. 26

8. Litteraturförteckning Bézier curve, Wikipedia. (den 20 2 2013a). Hämtat från Wikipedia: http://en.wikipedia.org/wiki/b%c3%a9zier_curve 2013 Cheat Engine. (u.d.). Cheat Engine. Hämtat från About Cheat Engine: http://www.cheatengine.org/aboutce.php den 2 5 2013 Data Scraping, Wikipedia. (den 24 4 2013b). Hämtat från Wikipedia: http://en.wikipedia.org/wiki/data_scraping den 2 5 2013 Drm0hr. (7 2012). File:Texas Hold'em Poker Table with Blinds.svg. Hämtat från Wikipedia: http://commons.wikimedia.org/wiki/file:texas_hold%27em_poker_table_with_blind s.svg den 2 5 2013 Glimne, D. (2005). Pokerhandboken. BW. Microsoft. (den 21 11 2012a). OpenProcess function. Hämtat från Microsoft: http://msdn.microsoft.com/enus/library/windows/desktop/ms684320%28v=vs.85%29.aspx den 2 5 2013 Microsoft. (den 26 10 2012b). ReadProcessMemory function. Hämtat från Microsoft: http://msdn.microsoft.com/enus/library/windows/desktop/ms680553%28v=vs.85%29.aspx den 2 5 2013 Niemeyer, P., & Knudsen, J. (2005). Learning Java. Nimcomsoft. (u.d.). Optical Character Recognition (OCR) How it works. Hämtat från Nicomsoft: http://www.nicomsoft.com/optical-character-recognition-ocr-how-it-works/ den 2 5 2013 Oracle. (2010). Class Robot. Hämtat från oracle.com: http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/robot.html den 2 5 2013 Pokerstars. (2013). Användarvillkor för PokerStars onlinepokerprogram. Hämtat från Pokerstars: http://www.pokerstars.se/poker/room/tos/ den 2 5 2013 Tulleken, H. (den 5 4 2011). Bézier Curves for your Games: A Tutorial. Hämtat från devmag.org.za: http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/ den 2 5 2013 Wikipedia. (den 2 4 2013c). Java Native Access. Hämtat från Wikipedia: http://en.wikipedia.org/wiki/java_native_access den 5 2 2013 Wikipedia. (den 30 4 2013d). Random-access memory. Hämtat från Wikipedia: http://en.wikipedia.org/wiki/random-access_memory den 5 2 2013 27