Advertisement
Guest User

YGO Deck Tool 2016/10/02

a guest
Oct 3rd, 2016
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
R 7.36 KB | None | 0 0
  1. setwd("~/R/Projects/Deck Tester")
  2.  
  3. ## DECK TOOL rev. 2016/10/02 ================================================
  4. #
  5. # This tool performs several functions that assist deck-building in trading
  6. # card games.  I developed this tool to reduce deck-building time and improve
  7. # the accuracy and efficiency of play-testing,  This tool is also
  8. # significantly more accurate efficient than sampling randomly drawn hands,
  9. # because it bases calculations on all possible hands.
  10. #
  11. # 1. GENERATE ALL POSSIBLE UNIQUE HANDS: This is useful for learning a new
  12. #     deck and determining what kind of hands are playable.
  13. #
  14. # 2. CALCULATE PERCENTAGE OF HANDS THAT MEET CRITERIA: This is useful for
  15. #     measuring combo consistency and refining card ratios.
  16. #
  17. # To use this tool, please place the R script in the same directory as the
  18. # deck list you want to use it with and set working directory to the source
  19. # file location.  For best results, your deck list should be a *.txt file,
  20. # and it should only contain cards in the deck that you draw from at the
  21. # beginning of the game.  Each line of the *.txt file should be formatted as
  22. # 'quantity [tab] # card name,' like so:
  23. #
  24. #     3     Cardcar D
  25. #
  26. # If any cards in your deck have any characteristics (level, attribute, card
  27. # type, etc.) that you would like to test for, append them to the card name
  28. # using abbreviations that are identifiable to you, but are not a part of any
  29. # other card names (e.g. [4] for Level 4, [r] for Ritual, etc.).
  30. #
  31. # To perform a criteria test, create a vector of abbreviations or names for
  32. # desired cards and assign it to the 'crit' argument in the function call. A
  33. # criteria test can be performed without generating readable hands.
  34. #
  35. # To produce readable hands, set the 'hgen' argument to TRUE.  The output
  36. # will include all unique hands or, if a criteria test is performed, only
  37. # hands that meet the tested criteria.  For your future reference, the
  38. # function will produce a *.txt file containing the same hands.  The number
  39. # at the beginning of each line indicates how many times that hand repeats.
  40. #
  41. # To further meet your testing needs, you can adjust the number of cards to
  42. # draw in each hand by assigning a new number to the 'draw' arugment.  The
  43. # default is 5, which is the number of starting cards in Yu-Gi-Oh!  Please
  44. # be aware that increasing the number of cards drawn may significantly
  45. # increase function run time.
  46. #
  47. # If your deck contains a draw-one effect, such as 'Upstart Goblin' from
  48. # Yu-Gi-Oh!, and you would like to immediately resolve it in each hand it's
  49. # drawn, assign the 'upst' argument with its name.  If you don't have or
  50. # don't want to resolve these effects, leave the 'upst' argument blank by
  51. # assigning '' to it instead.  Resoling effects that draw more than one card
  52. # is currently not yet implemented.
  53.  
  54. deck <- function(dtxt, crit = c(),
  55.                  draw = 5, upst = 'Upstart Goblin', hgen = F) {
  56.   # dtxt:   *.txt file of deck list or previous output from deck()
  57.   # crit:   string vector of criteria to evaluate for each hand
  58.   # hgen:   generate readable output of unique hands
  59.   # draw:   draw additional card for going second
  60.   # upst:   immediately resolve draw-one effect, e.g. 'Upstart Goblin'
  61. # HELPER FUNCTIONS ----------------------------------------------------------
  62.   d_check <- function(deck) {
  63.     # deck:   main input arg
  64.     if (is.character(deck)) {
  65.       d_out <- read.delim(deck, header = F, stringsAsFactors = F)
  66.     } else if (is.data.frame(deck)) {
  67.       if (is.numeric(deck$V1) & is.factor(deck$V2)) {
  68.         d_out <- deck
  69.       } else {
  70.         stop('Input data frame is malformed.')
  71.       }
  72.     } else if (is.list(deck) & is.data.frame(deck[[1]])) {
  73.       if (is.numeric(deck[[1]]$V1) & is.factor(deck[[1]]$V2)) {
  74.         d_out <- deck[[1]]
  75.       } else {
  76.         stop('Input list is malformed.')
  77.       }
  78.     } else {
  79.       stop('Deck file must be *.txt, data frame, or list.')
  80.     }
  81.     d_size <- sum(d_out$V1)
  82.     if (d_size < 40 | d_size > 60 | any(d_out$V1 > 3)) {
  83.       stop('Deck must contain 40 to 60 cards, 3 copies per card or fewer.')
  84.     } else {
  85.       print(paste('Read deck containing', d_size, 'total cards.'))
  86.     }
  87.     return(d_out)
  88.   } # check deck validity
  89.   d_upst <- function(deck, upst) {
  90.     # deck:   data frame from d_check()
  91.     # upst:   main input arg
  92.     upst_idx <- grepl(upst, deck$V2, fixed = T)
  93.     if (any(upst_idx)) {
  94.       deck <- deck[!upst_idx, ]
  95.       print('Resolved \'Upstart Goblin\'.')
  96.     } else {
  97.       print('Deck does not contain \'Upstart Goblin\'.')
  98.     }
  99.     return(deck)
  100.   } # resolve 'Upstart Goblin'
  101.   d_c <- function(deck, crit) {
  102.     # deck:   data frame from d_check(), d_upst()
  103.     # crit:   main input arg
  104.     p_idx <- rep(F, nrow(deck))
  105.     for (i in 1:length(crit)) {
  106.       p_idx[grep(crit[i], deck$V2, fixed = T)] <- T
  107.     }
  108.     deck$V2[!p_idx] <- NA
  109.     print('Deck pre-filtered for criteria.')
  110.     return(deck)
  111.   } # filter deck for criteria
  112.   d_h <- function(deck, draw) {
  113.     # deck:   data frame from d_check(), d_upst(), or d_c()
  114.     # draw:   main input arg
  115.     h_all <- t(combn(rep(deck$V2, deck$V1), draw))
  116.     h_flat <- apply(h_all, 1, paste, collapse = '')
  117.     h_rep <- duplicated(h_flat)
  118.     h_uid <- 1:nrow(h_all)
  119.     h_uid[h_rep] <- match(h_flat[h_rep], h_flat)
  120.     print(paste('Generated', sum(!h_rep), 'unique hands.'))
  121.     return(list(unique.matrix(h_all), table(h_uid)))
  122.   } # create unique hands and repetitions
  123.   h_eval <- function(hand, crit) {
  124.     # hand:   vector of cards in hand
  125.     # crit:   vector of criteria for hand
  126.     p_ct <- 0
  127.     for (i in 1:length(crit)) {
  128.       if (any(grepl(crit[i], hand, fixed = T))) {
  129.         p_idx <- grep(crit[i], hand, fixed = T)[1]
  130.         hand <- hand[-p_idx]
  131.         p_ct <- p_ct + 1
  132.       }
  133.     }
  134.     if (p_ct == length(crit)) return(T) else return(F)
  135.   } # check hand for criteria
  136.   h_write <- function(hands, reps, dtxt) {
  137.     # hands:  matrix of unique hands from d_h()[[2]]
  138.     # reps:   vector of repetitions from d_h()[[3]]
  139.     # dtxt:   main input arg
  140.     if (is.character(dtxt)) {
  141.       h_out <- paste(sub('.[a-z]+$', '', dtxt), '_hand.txt', sep = '')
  142.     } else {
  143.       h_out <- paste(deparse(substitute(dtxt)), '_hand.txt', sep = '')
  144.     }
  145.     write.table(cbind(reps, hands), h_out, col.names = F, row.names = F)
  146.     print(paste(sep = '', 'Hands printed to \'', h_out, '\'.'))
  147.   } # write unique hands to *.txt
  148. # FUNCTION DEFINTION --------------------------------------------------------
  149.   d_out <- d_check(dtxt)
  150.   if (!hgen & !length(crit)) {
  151.     return(d_out)
  152.   } else {
  153.     d_gen <- if (length(upst)) d_upst(d_out) else d_out
  154.     d_uniq <- if (hgen) d_h(d_gen, draw) else d_h(d_c(d_gen, crit), draw)
  155.     u_hand <- d_uniq[[1]]
  156.     u_rp <- d_uniq[[2]]
  157.     if (!length(crit)) {
  158.       h_write(u_hand, u_rp, dtxt)
  159.       return(list(d_out, u_hand, u_rp))
  160.     } else {
  161.       c_ct <- nrow(u_hand)
  162.       p_key <- rep(F, c_ct)
  163.       print('Evaluating unique hands...')
  164.       for (i in 1:c_ct) {
  165.         p_key[i] <- h_eval(u_hand[i, ], crit)
  166.         print(paste(i, 'of', c_ct, ifelse(p_key[i], 'passed', 'failed')))
  167.       }
  168.       p_rate <- sum(u_rp[p_key])/sum(u_rp)
  169.       print(paste(sep = '', 'Criteria met: ', round(100*p_rate, 2), '%'))
  170.       if (hgen) h_write(u_hand[p_key, ], u_rp[p_key], dtxt)
  171.       return(list(d_out, u_hand[p_key, ], u_rp[p_key], crit, p_rate))
  172.     }
  173.   }
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement