Skip to content

Instantly share code, notes, and snippets.

@hugsy
Last active October 3, 2016 14:37
Show Gist options
  • Save hugsy/d1fbc225c05b9191c951 to your computer and use it in GitHub Desktop.
Save hugsy/d1fbc225c05b9191c951 to your computer and use it in GitHub Desktop.
VolgaCTF 2016 - TicTacToe (PPC 200)
#!/usr/bin/env python2
#
# VolgaCTF 2016 - TicTacToe (PPC 200)
#
# @_hugsy_
# $ ./tic-tac-toe.py
# [...]
# Blocking computer in 5 with X
# Declaring draw for round=500
# Starting new round 500
# Congratulations! Your flag is: VolgaCTF{tic_t@c_t0e_is_the_e@rly_step_t0wards_AI}
import telnetlib
HOST = "tic-tac-toe.2016.volgactf.ru"
PORT = 45679
def build_socket(host, port):
s = telnetlib.Telnet(HOST, PORT)
print("Connected to %s:%d" % (host, port))
return s
def get_configuration(s):
blocks = []
for i in range(3):
line = s.read_until("\n").replace('\n', '')
for part in line.split("|"):
blocks.append( part.strip() )
line = s.read_until("\n").replace('\n', '')
return blocks
def is_free(b):
return b == ''
def has_lost_setup(cfg, cpu):
return ( (cfg[0]==cpu and cfg[1]==cpu and cfg[2]==cpu) # horizontal
or (cfg[3]==cpu and cfg[4]==cpu and cfg[5]==cpu)
or (cfg[6]==cpu and cfg[7]==cpu and cfg[8]==cpu)
or (cfg[0]==cpu and cfg[3]==cpu and cfg[6]==cpu) # vertical
or (cfg[1]==cpu and cfg[4]==cpu and cfg[7]==cpu)
or (cfg[2]==cpu and cfg[5]==cpu and cfg[8]==cpu)
or (cfg[0]==cpu and cfg[4]==cpu and cfg[8]==cpu) # diagonale
or (cfg[2]==cpu and cfg[4]==cpu and cfg[6]==cpu) # diagonale
)
def block_attack(cfg, cpu):
# horizontal
if (cfg[0]==cpu and is_free(cfg[1]) and cfg[2]==cpu): return 1
if (cfg[3]==cpu and is_free(cfg[4]) and cfg[5]==cpu): return 4
if (cfg[6]==cpu and is_free(cfg[7]) and cfg[8]==cpu): return 7
# vertical
if (cfg[0]==cpu and is_free(cfg[3]) and cfg[6]==cpu): return 3
if (cfg[1]==cpu and is_free(cfg[4]) and cfg[7]==cpu): return 4
if (cfg[2]==cpu and is_free(cfg[5]) and cfg[8]==cpu): return 5
# diagonal
if (cfg[0]==cpu and is_free(cfg[4]) and cfg[8]==cpu): return 4
if (cfg[2]==cpu and is_free(cfg[4]) and cfg[6]==cpu): return 4
# horizontal
if (cfg[0]==cpu and cfg[1]==cpu and is_free(cfg[2]) ): return 2
if (cfg[3]==cpu and cfg[4]==cpu and is_free(cfg[5]) ): return 5
if (cfg[6]==cpu and cfg[7]==cpu and is_free(cfg[8]) ): return 8
if (cfg[2]==cpu and cfg[1]==cpu and is_free(cfg[0]) ): return 0
if (cfg[5]==cpu and cfg[4]==cpu and is_free(cfg[3]) ): return 3
if (cfg[8]==cpu and cfg[7]==cpu and is_free(cfg[6]) ): return 6
#vertical
if (cfg[0]==cpu and cfg[3]==cpu and is_free(cfg[6]) ): return 6
if (cfg[1]==cpu and cfg[4]==cpu and is_free(cfg[7]) ): return 7
if (cfg[2]==cpu and cfg[5]==cpu and is_free(cfg[8]) ): return 8
if (cfg[6]==cpu and cfg[3]==cpu and is_free(cfg[0]) ): return 0
if (cfg[7]==cpu and cfg[4]==cpu and is_free(cfg[1]) ): return 1
if (cfg[8]==cpu and cfg[5]==cpu and is_free(cfg[2]) ): return 2
#diagonal
if (cfg[0]==cpu and cfg[4]==cpu and is_free(cfg[8]) ): return 8
if (cfg[6]==cpu and cfg[4]==cpu and is_free(cfg[2]) ): return 2
if (cfg[8]==cpu and cfg[4]==cpu and is_free(cfg[0]) ): return 0
if (cfg[2]==cpu and cfg[4]==cpu and is_free(cfg[6]) ): return 6
return -1
def is_winning_setup(cfg, me):
return block_attack(cfg, me)
def get_nb_busy(c):
n = 0
for i in range(len(c)):
if not is_free(c[i]):
n+=1
return n
def is_draw(c):
return get_nb_busy(c) == 9
def pprint(cfg):
for i in range(0,9,3):
line = "| "
for j in range(3):
line += cfg[i+j] if cfg[i+j]!='' else ' '
line += " | "
print(line)
print('')
return
def start_game(s):
print("Starting game")
for i in range(2000):
print("Starting new round %d" % i)
new_round(s)
return
def new_round(s):
rnd = s.read_until("\n").strip()
if "Final score:" in rnd:
while True:
print s.read_until("\n")
exit(0)
rnd = rnd.split()[2][:-1]
rnd = int(rnd)
score = s.read_until("\n").strip().split()[5:]
print("Score (cpu/me): %s" % ' '.join(score))
is_first_move = True
computer_starts_first = False
computer = None
while True:
cfg = get_configuration(s)
print("Current configuration:")
pprint(cfg)
if is_first_move:
for b in cfg:
if len(b)=='': continue
if b in ('X', 'O'):
computer = b
me = 'O' if computer=='X' else 'X'
computer_starts_first = True
break
if computer is None:
computer_starts_first = False
computer = 'O'
me = 'X'
if computer_starts_first:
print("Computer starts first round=%d with %c" % (rnd, computer))
else:
print("Player starts first round=%d with %c" % (rnd, computer))
is_first_move = False
ret = is_winning_setup(cfg, me)
if ret >= 0:
# make winning move, and return
print("Winning round=%d" % rnd)
s.write("%d\n" % ret)
return
ret = block_attack(cfg, computer)
if ret >= 0:
print("Blocking computer in %d with %c" % (ret, me))
s.write("%d\n" % ret)
if get_nb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment