2023-11-22 11:03:01 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
rewrite bot
diff --git a/yacht.lua b/yacht.lua index 731037d..c0a5432 100644 --- a/yacht.lua +++ b/yacht.lua @@ -5,6 +5,14 @@ local cats = { "choice", "yacht", "1s", "2s", "3s", "4s", "5s", "6s" } +local function cat_index(cat) + for i, c in ipairs(cats) do + if c == cat then + return i + end + end +end + local function calc_total(sheet) local total = 0 for _, cat in ipairs(cats) do @@ -121,28 +129,28 @@ function Yacht:run_round() local sheet = self.sheets[i] local is_bot = p:sub(1, 1) == "C" local dice = self:do_rolls(is_bot) - local sel + local cat if is_bot then - sel = self.bot:pick(sheet, dice) + cat = self.bot:pick(sheet, dice) + assert(sheet[cat] == nil and cat_index(cat) ~= nil) self.term:delay(1) - for cur, cat in ipairs(cats) do - if sheet[cat] == nil then + for cur, curcat in ipairs(cats) do + if sheet[curcat] == nil then self:putsel(cur) self.term:delay(2) self:remsel(cur) - if cur == sel then + if curcat == cat then break end end end self.term:delay(2) else - sel = self:pick() + cat = cats[self:pick()] end - local cat = cats[sel] local points = calc_points(dice, cat) sheet[cat] = points - self:putpoints(sel, points) + self:putpoints(cat_index(cat), points) self.term:goto(2+7*(i-1), 2) io.write(("%3d"):format(calc_total(sheet))) self.term:get_key() @@ -386,44 +394,155 @@ end local Bob = {} Bob.__index = Bob +local function log(msg) + --~ io.write("\x1B7") -- save cursor position + --~ io.write("\x1B[15;1H") -- goto row 15, col 1 + --~ io.write("\x1B[2K") -- clear line + --~ io.write(msg) -- print msg + --~ io.write("\x1B8") -- restore cursor position +end + function Bob:select(sheet, dice, roll) local sum, hist, min_count, max_count = calc_data(dice) local sel = {} - if max_count > 1 then + if sheet["full-house"] == nil then + local rep = {} + for i = 3, 6 do + if hist[i] >= 2 then + table.insert(rep, i) + end + end + if #rep == 2 then + for i = 1, 5 do + sel[i] = hist[dice[i]] >= 2 + end + log("full-house") + return sel + end + end + if sheet["yacht"] == nil and max_count >= 4 then for i = 1, 5 do - sel[i] = hist[dice[i]] == max_count + sel[i] = hist[dice[i]] >= 4 end + log("yacht") + return sel end - return sel + if sheet["little-straight"] == nil or sheet["big-straight"] == nil then + local little_match, big_match + little_match = (hist[1] > 0) and 1 or 0 + big_match = (hist[6] > 0) and 1 or 0 + for i = 2, 5 do + if hist[i] > 0 then + little_match = little_match + 1 + big_match = big_match + 1 + end + end + local cat + if sheet["little-straight"] ~= nil then + if big_match >= 4 then + cat = "big-straight" + end + elseif sheet["big-straight"] ~= nil then + if little_match >= 4 then + cat = "little-straight" + end + elseif math.max(big_match, little_match) >= 4 then + if big_match > little_match then + cat = "big-straight" + else + cat = "little-straight" + end + end + local tosel + if cat == "little-straight" then + tosel = {1, 1, 1, 1, 1, 0} + elseif cat == "big-straight" then + tosel = {0, 1, 1, 1, 1, 1} + end + if cat ~= nil then + for i = 1, 5 do + local d = dice[i] + if tosel[d] > 0 then + sel[i] = true + tosel[d] = tosel[d] - 1 + end + end + log(cat) + return sel + end + end + if max_count >= 3 or sheet["choice"] ~= nil or sum < 12 then + local d + for i = 1, 6 do + if hist[i] == max_count then + d = i + break + end + end + local cat = cats[d+6] + if sheet[cat] == nil or (sheet["four-of-a-kind"] == nil and d > 3) then + for i = 1, 5 do + sel[i] = dice[i] == d + end + log("repeat "..d) + return sel + end + end + if sheet["choice"] == nil then + for i = 1, 5 do + sel[i] = dice[i] > 3 + end + log("choice") + return sel + end + log("discard roll") + return {} end function Bob:pick(sheet, dice, roll) - local min_points, max_points = 99, 0 - local sel, sel_min, sel_max - for cur, cat in ipairs(cats) do - if sheet[cat] == nil then - local points = calc_points(dice, cat) - if points > max_points then - sel_max = cur - max_points = points - end - if points > 0 and points < min_points then - sel_min = cur - min_points = points - end + local sum, hist, min_count, max_count = calc_data(dice) + local good_cats = {"yacht", "four-of-a-kind", "full-house", "little-straight", "big-straight"} + local good_mins = {1, 16, 17, 1, 1} + for i, cat in ipairs(good_cats) do + local thresh = good_mins[i] + if sheet[cat] == nil and calc_points(dice, cat) >= thresh then + log("good match: "..cat) + return cat end end - if max_points > 20 or (sel_max ~= nil and sel_max > 6) then - sel = sel_max - else - sel = sel_min + if sheet["choice"] == nil and sum >= 20 then + log("ok match: choice") + return "choice" end - if sel == nil then - repeat - sel = self.prng:randint(1, #cats) - until sheet[cats[sel]] == nil + for i = 1, 6 do + local cat = i.."s" + if sheet[cat] == nil and hist[i] >= 2 then + log("ok match: "..cat) + return cat + end end - return sel + -- no good pick, discard a sane item + local bad_cats = {"1s", "2s", "3s", "little-straight", "big-straight"} + for _, cat in ipairs(bad_cats) do + if sheet[cat] == nil then + log("discard bad") + return cat + end + end + -- discard anything with points (useful on last few rounds) + for _, cat in ipairs(bad_cats) do + if sheet[cat] == nil and calc_points(dice, cat) > 0 then + log("discard with points") + return cat + end + end + -- no sane discard possible, discard anything + log("insane discard") + local cat + repeat + cat = cats[self.prng:randint(1, 12)] + until sheet[cat] == nil + return cat end local yacht = new_yacht(Bob)