HAI OBTW Basic Markov-chain implementation (specific to RPS competition) in LOLCode. Accessor functions aren't very LOLy, but a good :%s/fn_name/LULZNAEM/g will fix that completely. TLDR OBTW join ----- Basic array join functionality. TLDR HOW DUZ I join YR a AN YR b I HAS A count ITZ ALL a LOL count R count NERF 1 IZ count SMALR THAN 0 ? FOUND YR "" I HAS A output ITZ "" IM IN YR LOOP LOL output R count IN MAH a N output IZ count BIGR THAN 0 ? LOL output R b N output IZ count LIEK 0 ? GTFO LOL count R count NERF 1 KTHX FOUND YR output IF U SAY SO OBTW push ----- Basic array push functionality. TLDR HOW DUZ I push YR IT AN YR value I HAS A PLAES ITZ ALL IT LOL PLAES IN MAH IT R value IF U SAY SO OBTW addVectors ----- Adds two arrays as vectors. TLDR HOW DUZ I addVectors YR v1 AN YR v2 I HAS A v3 I HAS A max ITZ ALL v1 I HAS A d2 ITZ ALL v2 IZ d2 BIGR THAN max ? LOL max R d2 I HAS A base ITZ 0 IM IN YR LOOP IZ base LIEK max ? GTFO LOL base IN MAH v3 R base IN MAH v1 UP base IN MAH v2 UP base!! KTHX FOUND YR v3 IF U SAY SO OBTW getThrowNameById ----- Returns R, P, or S based on the int code passed in. TLDR HOW DUZ I getThrowNameById YR id IZ id LIEK 0 ? FOUND YR "R" IZ id LIEK 1 ? FOUND YR "P" IZ id LIEK 2 ? FOUND YR "S" BTW Without throw, just barf the proggy DIAF "Invalid throwID" IF U SAY SO OBTW getThrowIdByName ----- Returns 0, 1, or 2 based on the throwtype passed in. TLDR HOW DUZ I getThrowIdByName YR name IZ name LIEK "R" ? FOUND YR 0 IZ name LIEK "P" ? FOUND YR 1 IZ name LIEK "S" ? FOUND YR 2 BTW Without throw, just barf the proggy DIAF "Invalid throwName" IF U SAY SO OBTW generateRandomThrow ----- Returns a random throwName. TLDR HOW DUZ I generateRandomThrow I HAS A schroedinger_kitteh ITZ MEBBE 0 MEBBE 2 FOUND YR getThrowNameById YR schroedinger_kitteh MKAY IF U SAY SO OBTW generateComplementThrowFromModels ----- Given remote and local histories and Markovs, generates the best response. TLDR HOW DUZ I generateComplementThrowFromModels YR m1 AN YR h1 AN YR m2 AN YR h2 I HAS A v1 ITZ generateThrowVotesFromModel YR m1 AN YR h1 MKAY I HAS A v2 ITZ generateThrowVotesFromModel YR m2 AN YR h2 MKAY I HAS A v ITZ addVectors YR v1 AN YR v2 MKAY I HAS A throw_index ITZ arrayMaxIndex YR v MKAY I HAS A generated_throw ITZ getThrowNameById YR throw_index MKAY IZ generated_throw LIEK "R" ? FOUND YR "P" IZ generated_throw LIEK "P" ? FOUND YR "S" IZ generated_throw LIEK "S" ? FOUND YR "R" DIAF "Unknown throw to complement: " N generated_throw N ". Aborting." IF U SAY SO OBTW generateComplementThrowFromModel ----- Given a model and a history, returns the *beating* throw. TLDR HOW DUZ I generateComplementThrowFromModel YR markov AN YR history I HAS A throw ITZ generateThrowFromModel YR markov AN YR history MKAY IZ throw LIEK "R" ? FOUND YR "P" IZ throw LIEK "P" ? FOUND YR "S" IZ throw LIEK "S" ? FOUND YR "R" DIAF "Unknown throw to complement: " N throw N ". Aborting." IF U SAY SO OBTW generateThrowFromModel ----- Given a model and a history, returns the most likely next throw. TLDR HOW DUZ I generateThrowVotesFromModel YR markov AN YR history I HAS A LENF ITZ 10 I HAS A CUTOFF ITZ 0 I HAS A count ITZ 3 IN MAH 0 IN MAH markov UP 3 IN MAH 1 IN MAH markov UP 3 IN MAH 2 IN MAH markov I HAS A throw I HAS A votes LOL 0 IN MAH votes R 0 LOL 1 IN MAH votes R 0 LOL 2 IN MAH votes R 0 IZ count SMALR THAN CUTOFF O RLY? YA RLY VISIBLE ":: Insufficient history; generating random throw." BTW LOL throw R generateRandomThrow MKAY BTW ::: Cheating... LOL throw R MEBBE 0 MEBBE 2 LOL throw IN MAH votes R 1 FOUND YR votes KTHX BTW ::: This is where the magix happens. I HAS A history_length ITZ ALL history I HAS A base ITZ history_length NERF LENF IZ base SMALR THAN 0 ? LOL base R 0 I HAS A _base ITZ base I HAS A play I HAS A play_index I HAS A _markov I HAS A sum_votes I HAS A prod_votes I HAS A weight I HAS A round_weight BTW ::: HFS digits can only be placed at the end of an arithmetic expression. WTF was I thinking? I HAS A weight_base ITZ 1 I HAS A vote_index I HAS A vote_weight IM IN YR OUTIE IZ _base LIEK history_length ? GTFO LOL base R _base LOL _markov R markov LOL round_weight R weight_base BOOMZ ( history_length NERF _base ) IM IN YR INNIE BTW IZ base LIEK history_length ? GTFO IZ base LIEK history_length O RLY? YA RLY BTW ::: Clearly, need to fix math functions... LOL sum_votes R 3 IN MAH 0 IN MAH _markov UP 3 IN MAH 1 IN MAH _markov UP 3 IN MAH 2 IN MAH _markov UP 1 LOL prod_votes R 3 IN MAH 0 IN MAH _markov UP 1 LOL prod_votes R prod_votes TIEMZ ( 3 IN MAH 1 IN MAH _markov UP 1 ) LOL prod_votes R prod_votes TIEMZ ( 3 IN MAH 2 IN MAH _markov UP 1 ) LOL weight R sum_votes OVARZ prod_votes LOL vote_index R 0 IM IN YR LOOP IZ vote_index LIEK 3 ? GTFO LOL vote_weight R 3 IN MAH vote_index IN MAH _markov OVARZ sum_votes LOL vote_weight R vote_weight TIEMZ weight TIEMZ round_weight LOL vote_index IN MAH votes R vote_index IN MAH votes UP vote_weight UP vote_index!! KTHX GTFO KTHX LOL play R base IN MAH history LOL play_index R getThrowIdByName YR play MKAY LOL _markov R play_index IN MAH _markov UP base!! KTHX UP _base!! BTW ::: For testing, take the 10-count only BTW ::: GTFO KTHX BTW VISIBLE "-----\n" N "R: " N 0 IN MAH votes N "\nP: " N 1 IN MAH votes N "\nS: " N 2 IN MAH votes N "\n-----" FOUND YR votes IF U SAY SO OBTW arrayMaxIndex ------ Given an array, returns the index of the maximal element (or rand if there are multiple equals). (yes, it obfuscates the rand behaviour; don't give me lip) TLDR HOW DUZ I arrayMaxIndex YR array I HAS A LENF ITZ ALL array IZ LENF LIEK 0 ? FOUND YR -1 I HAS A max_value ITZ 0 IN MAH array I HAS A index ITZ 1 I HAS A max_index LOL 0 IN MAH max_index R 0 I HAS A max_count ITZ 1 IM IN YR LOOP IZ index LIEK LENF ? GTFO IZ index IN MAH array BIGR THAN max_value O RLY? YA RLY LOL max_value R index IN MAH array LOL max_count R 1 LOL 0 IN MAH max_index R index NO WAI IZ index IN MAH array LIEK max_value O RLY? YA RLY LOL max_count IN MAH max_index R index UP max_count!! KTHX KTHX UP index!! KTHX IZ max_count LIEK 1 ? FOUND YR 0 IN MAH max_index I HAS A return_index ITZ MEBBE 0 MEBBE max_count NERF 1 FOUND YR return_index IN MAH max_index IF U SAY SO OBTW getErrorCode ----- Returns the error code of the response XML (passed) TLDR HOW DUZ I getErrorCode YR xml I HAS A count ITZ 0 I HAS A max ITZ ALL xml I HAS A errorcode IM IN YR LOOP IZ count LIEK max ? GTFO IZ count IN MAH xml SORTA "\s*(\d+)\s*" O RLY? YA RLY LOL errorcode R SORTA 1 FOUND YR errorcode KTHX UP count!! KTHX IZ errorcode SORTA "\d+" ? FOUND YR errorcode DIAF "No error code found." IF U SAY SO OBTW genericRegexMatch ----- Iterates a regex over array contents (so that you don't have to) . This will only pick the first matching line . Even if we changed that, it'd probably only pick the first match per line TLDR HOW DUZ I genericRegexMatch YR xml AN YR regex I HAS A count ITZ 0 I HAS A max ITZ ALL xml I HAS A match IM IN YR LOOP IZ count LIEK max ? GTFO IZ count IN MAH xml SORTA regex O RLY? YA RLY LOL 1 IN MAH match R SORTA 1 LOL 2 IN MAH match R SORTA 2 LOL 3 IN MAH match R SORTA 3 LOL 4 IN MAH match R SORTA 4 LOL 5 IN MAH match R SORTA 5 LOL 6 IN MAH match R SORTA 6 LOL 7 IN MAH match R SORTA 7 LOL 8 IN MAH match R SORTA 8 LOL 9 IN MAH match R SORTA 9 FOUND YR match KTHX UP count!! KTHX FOUND YR match IF U SAY SO OBTW getOpponentPlay ----- Gets the other person's throw based on the local throw and the result. TLDR HOW DUZ I getOpponentPlay YR play AN YR result I HAS A opponent_play IZ result LIEK "Win" O RLY? YA RLY IZ play LIEK "R" ? FOUND YR "S" IZ play LIEK "P" ? FOUND YR "R" FOUND YR "P" NO WAI IZ result LIEK "Lose" O RLY? YA RLY IZ play LIEK "R" ? FOUND YR "P" IZ play LIEK "P" ? FOUND YR "S" FOUND YR "R" NO WAI FOUND YR play KTHX KTHX BTW ::: Due to the conditional structure above, we should never get here. DIAF "Unexpected game status: " N result N ". Aborting." IF U SAY SO OBTW addArrayToMarkov ----- Adds the [n] suffix of an array to a Markov chain. TLDR HOW DUZ I addArrayToMarkov YR array AN YR markov AN YR play I HAS A LENF ITZ 11 I HAS A max ITZ ALL array I HAS A base ITZ max NERF LENF I HAS A NUFFIN IZ base SMALR THAN 0 ? LOL base R 0 IM IN YR LOOP IZ base LIEK max UP 1 ? GTFO LOL LENF R max NERF base LOL NUFFIN R addArraySuffixToMarkov YR array AN YR markov AN YR play AN YR LENF MKAY UP base!! KTHX IF U SAY SO OBTW addArraySuffixToMarkov ----- Adds an [n] length array suffix to a Markov chain. TLDR HOW DUZ I addArraySuffixToMarkov YR array AN YR markov AN YR play AN YR LENF I HAS A max ITZ ALL array I HAS A base ITZ max NERF LENF I HAS A _markov ITZ markov I HAS A _play_index IZ base SMALR THAN 0 ? LOL base R 0 IM IN YR LOOP IZ base LIEK max ? GTFO LOL _play_index R getThrowIdByName YR base IN MAH array MKAY LOL _markov R _play_index IN MAH _markov UP base!! KTHX LOL _play_index R getThrowIdByName YR play MKAY LOL _markov R _play_index IN MAH _markov LOL 3 IN MAH _markov R 3 IN MAH _markov UP 1 IF U SAY SO OBTW getRandomArrayElement ----- Returns an element at random from an array. TLDR HOW DUZ I getRandomArrayElement YR array I HAS A LENF ITZ ALL array I HAS A index ITZ MEBBE 0 MEBBE LENF NERF 1 FOUND YR index IN MAH array IF U SAY SO OBTW getTestPlayByHistory ----- Given an opponent's history, returns the play we'd like them to make (to test). TLDR HOW DUZ I getTestPlayByHistory YR history BTW BTW ::: Single-play test BTW OBTW FOUND YR "R" TLDR BTW BTW ::: Random-play test BTW OBTW I HAS A play_index ITZ MEBBE 0 MEBBE 2 FOUND YR getThrowNameById YR play_index MKAY TLDR BTW BTW ::: Two-play test BTW OBTW I HAS A round ITZ ALL history IZ round SORTA "[02468]$" ? FOUND YR "R" FOUND YR "P" TLDR BTW BTW :: Ten-play test BTW :: . not so great for 9x, 1x... would require only ten-point history to master that one OBTW I HAS A scheme LOL 0 IN MAH scheme R "P" LOL 1 IN MAH scheme R "S" LOL 2 IN MAH scheme R "R" LOL 3 IN MAH scheme R "R" LOL 4 IN MAH scheme R "S" LOL 5 IN MAH scheme R "P" LOL 6 IN MAH scheme R "S" LOL 7 IN MAH scheme R "R" LOL 8 IN MAH scheme R "S" LOL 9 IN MAH scheme R "S" I HAS A round ITZ ALL history IZ round SORTA "([0-9])$" O RLY? YA RLY LOL round R SORTA 1 FOUND YR round IN MAH scheme KTHX TLDR BTW BTW :: Mirror test BTW I HAS A lenf ITZ ALL history I HAS A offset ITZ 30 IZ lenf SMALR THAN offset ? FOUND YR generateRandomThrow MKAY LOL lenf R lenf NERF offset FOUND YR lenf IN MAH history FOUND YR generateRandomThrow MKAY DIAF "Unrecognized index!" IF U SAY SO OBTW getGameStatus ----- Given a P1 play and a P2 play, returns the game status for P1. TLDR HOW DUZ I getGameStatus YR p1 AN YR p2 IZ p1 LIEK p2 ? FOUND YR "Tie" IZ p1 LIEK "R" O RLY? YA RLY IZ p2 LIEK "P" ? FOUND YR "Lose" IZ p2 LIEK "S" ? FOUND YR "Win" BTW ::: NULL op to prevent from crashing :( NO WAI IZ p1 LIEK "P" O RLY? YA RLY IZ p2 LIEK "S" ? FOUND YR "Lose" IZ p2 LIEK "R" ? FOUND YR "Win" BTW ::: NULL op to prevent from crashing :( NO WAI IZ p1 LIEK "S" O RLY? YA RLY IZ p2 LIEK "R" ? FOUND YR "Lose" IZ p2 LIEK "P" ? FOUND YR "Win" BTW ::: NULL op to prevent from crashing :( KTHX KTHX KTHX DIAF "Error: bad game status passed to getGameStatus. Aborting." IF U SAY SO OBTW LOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOL Thus begins the main script. LOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOL TLDR BTW ::: Useful constants BTW ::: (but since LOLCode has no constants, they're just as editable) I HAS A RAND ITZ MEBBE 1 MEBBE 1000 LOL RAND R "" I HAS A NAEM ITZ "ROFLBOT" N RAND I HAS A PKTUR ITZ "http://flyinggenitalavatar.homestead.com/do.not.panic.at.the.disco.jpg" I HAS A PLAESTOGO ITZ "http://keith-hp:8085/RocksYourSocks/RPS.asmx" VISIBLE "ROFLBOTv1.0" VISIBLE "-----------" VISIBLE "Beginning gameplay." BTW ::: General variables I HAS A local_play_history I HAS A local_play_markov I HAS A remote_play_history I HAS A remote_play_markov I HAS A error_code I HAS A error_status I HAS A ALLEYCAT I HAS A game_id I HAS A play I HAS A opponent_play I HAS A game_history_string I HAS A WIN I HAS A WINSTRY I HAS A NUFFIN I HAS A round LOL 0 IN MAH WINSTRY R 0 LOL 1 IN MAH WINSTRY R 0 LOL 2 IN MAH WINSTRY R 0 BTW ::: Test variables (wrap in OBTW...TLDR at some point) I HAS A testing ITZ 0 I HAS A server_game_responses LOL 0 IN MAH server_game_responses R "Tie" LOL 1 IN MAH server_game_responses R "Win" LOL 2 IN MAH server_game_responses R "Lose" BTW ::: Connect to the RPS server. I HAS A server_connection GIMMEH LINEZ server_connection OUTTA PLAESTOGO N "/RegisterPlayer?strPlayerName=" N NAEM N "&strIconUrl=" N PKTUR VISIBLE "Beginning tournament.\n" BTW ::: Error-handling? BTW ::: Loop indefinitely. IM IN YR TRNAMNT IZ testing LIEK 1 O RLY? NO WAI GIMMEH LINEZ server_connection OUTTA PLAESTOGO N "/StartGame" LOL error_code R getErrorCode YR server_connection MKAY BTW ::: Check server response. IZ error_code LIEK 0 O RLY? NO WAI LOL error_status R genericRegexMatch YR server_connection AN YR "\s*(.*?)\s*" MKAY VISIBLE "Ending game (message: " N 1 IN MAH error_status N ")\n" GTFO KTHX LOL ALLEYCAT R genericRegexMatch YR server_connection AN YR "\s*(.*?)\s*" MKAY LOL game_id R genericRegexMatch YR server_connection AN YR "\s*(.*?)\s*" MKAY LOL game_id R 1 IN MAH game_id VISIBLE "New game! (now playing " N 1 IN MAH ALLEYCAT N ")" KTHX LOL 0 IN MAH WINSTRY R 0 LOL 1 IN MAH WINSTRY R 0 LOL 2 IN MAH WINSTRY R 0 BTW ::: Loop the game while necessary. IM IN YR GAEM LOL play R generateComplementThrowFromModels YR remote_play_markov AN YR remote_play_history AN YR local_play_markov AN YR local_play_history MKAY BTW VISIBLE ":: :: throwing " N play BTW ::: Check server response. IZ testing LIEK 1 O RLY? YA RLY BTW VISIBLE ":: Playing from history:" BTW LOL error_status R join YR remote_play_history AN YR ", " MKAY BTW VISIBLE ":: :: " N error_status BTW LOL 1 IN MAH WIN R getRandomArrayElement YR server_game_responses MKAY LOL opponent_play R getTestPlayByHistory YR remote_play_history MKAY LOL 1 IN MAH WIN R getGameStatus YR play AN YR opponent_play MKAY NO WAI GIMMEH LINEZ server_connection OUTTA PLAESTOGO N "/Throw?strThrow=" N play N "&strGameId=" N game_id LOL error_code R getErrorCode YR server_connection MKAY IZ error_code LIEK 0 O RLY? NO WAI BTW ::: Parse return and display LOL error_status R genericRegexMatch YR server_connection AN YR "\s*(.*?)\s*" MKAY VISIBLE "Game over (" N 1 IN MAH error_status N ")" GTFO KTHX LOL WIN R genericRegexMatch YR server_connection AN YR "\s*(.*?)\s*" MKAY IZ 1 IN MAH WIN LIEK "Invalid" O RLY? YA RLY BTW ::: Bad throw, or something. LOL error_status R genericRegexMatch YR server_connection AN YR "\s*(.*?)\s*" MKAY VISIBLE "Game error (" N 1 IN MAH error_status N ")" KTHX KTHX IZ 1 IN MAH WIN LIEK "Win" ? LOL 0 IN MAH WINSTRY R 0 IN MAH WINSTRY UP 1 IZ 1 IN MAH WIN LIEK "Tie" ? LOL 1 IN MAH WINSTRY R 1 IN MAH WINSTRY UP 1 IZ 1 IN MAH WIN LIEK "Lose" ? LOL 2 IN MAH WINSTRY R 2 IN MAH WINSTRY UP 1 BTW ::: Add play information to our history. LOL opponent_play R getOpponentPlay YR play AN YR 1 IN MAH WIN MKAY BTW VISIBLE ":: :: :: I played " N play N ". They played " N opponent_play N ". I " N 1 IN MAH WIN N "." LOL game_history_string R join YR WINSTRY AN YR " | " MKAY VISIBLE ":: :: :: New game history: " N game_history_string LOL round R 0 IN MAH WINSTRY UP 1 IN MAH WINSTRY UP 2 IN MAH WINSTRY IZ round BIGR THAN 999 ? GTFO BTW ::: And use the history to build a Markov chain. BTW ::: BTW ::: Just pass the history arrays to a Markov builder function. BTW ::: What's the deal with first-, second-, and third-guessing? BTW ::: . Unnecessary for first player (just load-balance). What about opponent? BTW ::: BTW ::: Just have a guess-type array? LOL NUFFIN R addArrayToMarkov YR local_play_history AN YR local_play_markov AN YR opponent_play MKAY LOL NUFFIN R addArrayToMarkov YR remote_play_history AN YR remote_play_markov AN YR opponent_play MKAY LOL NUFFIN R push YR local_play_history AN YR play MKAY LOL NUFFIN R push YR remote_play_history AN YR opponent_play MKAY IZ testing LIEK 1 O RLY? YA RLY BTW VISIBLE "Press [ENTER] to continue (q to quit)... "! BTW GIMMEH LETTAR NUFFIN BTW IZ NUFFIN LIEK "q" ? GTFO BTW VISIBLE "" KTHX KTHX GIMMEH LINEZ server_connection OUTTA PLAESTOGO N "/GameSummary?strGameId=" N game_id VISIBLE "Game over" VISIBLE "" IZ testing LIEK 1 ? GTFO KTHX VISIBLE "No more games. Exiting." KTHXBYE