At first glance, Lucky Dice looks straightforward: watch players roll dice, figure out who won each round, and type the answer. Simple enough - until you notice the 0.3 second timeout and 100 rounds requirement. No human can reliably respond that fast, 100 times in a row. The challenge is telling you to write a bot.
Game Rules
1
100 rounds must be completed
2
8 to 13 players per round (randomized)
3
Dice grow each round:
dice_nr = rnd × 2 + 2
4
Each player's dice are summed → their score
5
Highest total wins the round
⚡
Tiebreaker: the last player (by roll order) with the highest score wins
6
0.3 seconds to submit your answer
The Timeout Check
Python
timeout = 0.3
start = time.time()
answer = input('> ')
if time.time() - start > timeout:
print("Mate... your are too slow! It seems your CPU is too old!")
return False
if answer != result:
print('Hey! I think your scoring is off... Check your RAM... It may be corrupted!')
return False
The Critical Edge Case: Tiebreaker
WRONG
winner = max(player_scores, key=lambda p: player_scores[p])
Returns the first player with max score — fails on ties!
CORRECT
winner = None
for player_num, score in players_ordered:
if score == max_score:
winner = player_num # overwrites → last match wins
Stores players in order and overwrites on ties → last player wins!
Full Solver Script
Python 3
#!/usr/bin/env python3
import socket
import re
HOST = "154.57.164.82"
PORT = 32011
def recv_until_prompt(s):
data = b""
while True:
try:
chunk = s.recv(4096)
if not chunk:
break
data += chunk
if data.endswith(b"> "):
break
except socket.timeout:
break
return data.decode("utf-8", errors="replace")
def solve():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.settimeout(10)
intro = recv_until_prompt(s)
print(intro)
s.sendall(b"1\n")
for rnd in range(100):
output = recv_until_prompt(s)
print(output)
lines = output.split("\n")
players_ordered = []
for line in lines:
m = re.match(r"Player\s+(\d+):\s+([\d\s]+)", line.strip())
if m:
player_num = int(m.group(1))
dice = list(map(int, m.group(2).strip().split()))
players_ordered.append((player_num, sum(dice)))
if not players_ordered:
print("[!] Could not parse player scores!")
break
max_score = max(score for _, score in players_ordered)
winner = None
for player_num, score in players_ordered:
if score == max_score:
winner = player_num
print(f" --> Round {rnd+1}: Winner = Player {winner} (score={max_score})")
s.sendall(f"{winner}\n".encode())
final = b""
try:
while True:
chunk = s.recv(4096)
if not chunk:
break
final += chunk
except:
pass
print("\n=== FINAL OUTPUT ===")
print(final.decode("utf-8", errors="replace"))
s.close()
if __name__ == "__main__":
solve()
Running the Solver
kali@htb
$ python3 lucky_dice_solver.py
=== Round 100 ===
Player 1: 4 2 6 ...
...
Who wins this round?
>
--> Round 100: Winner = Player 5 (score=742)
=== FINAL OUTPUT ===
Yes.. Correct!
Nice job!
Here is your prize:
HTB{xxxxxxxx-xxxxxx-xxxxxxxx}
=== Round 100 ===
Player 1: 4 2 6 ...
...
Who wins this round?
>
--> Round 100: Winner = Player 5 (score=742)
=== FINAL OUTPUT ===
Yes.. Correct!
Nice job!
Here is your prize:
HTB{xxxxxxxx-xxxxxx-xxxxxxxx}
