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