4 ms·
Implementing Tic Tac Toe with 170mb of HTML – No JavaScript or CSS
- slau 3y agoThe author used popovers to store state and calculate results. They also used JavaScript to generate the HTML. And hate properly capitalising “MB”. The demo indicates it only works on Chrome, however it worked fine on Firefox on iOS (so just Safari, presumably).
- arminluschin 3y agoYes, works in iOS Safari
- anonymoushn 3y ago170 millibits would be much more impressive
- cantSpellSober 3y ago> They also used JavaScript to generate the HTML They could have used any language to do this really. I think the title means "the final game runs without JS or CSS"
- splittydev 3y agoWorks fine on Safari 17.1, great work!
- kevincox 3y agoIt seems that there is a missed optimization where the order of moves after. Assuming that X always goes first for every board state you know who goes next and the path that you took to get there doesn't matter. So you don't have to store the full sequence of moves that lead to the state, just the state itself.
- xnx 3y ago170 MB seems like a lot. Aren't there less than 1,000 different states? My first naive idea would be to link to a static version of the gameboard further down the page like href="xo-------".
- Infinity315 3y agoEach tile can take on 3 states, x, o, and the empty state. 3^9 = 19683. Of course, this is also counting many invalid states where a player would have won and symmetries of the board.
- p4bl0 3y agoThere are 9 cells in the game that each can be empty, X, or O. So three states. That is 3^9 = 19683 maximum possible states of the game. 170MB seems like an awefull lot.
- peterhull90 3y ago> Popovertarget passes every choice made by the player, for example: x1-o2-x3 means X chooses the first position, O chooses the second and X chooses the third, and so on. I think this is going to lead to a lot of redundant states, isn't it, because there are multiple paths to get to a particular board layout?
- shultays 3y agoThere would be a lot of illegal states in that number.
- p4bl0 3y agoOf course, that's why I said "maximum". That strengthen my point.
- p4bl0 3y agoIt seems there are only 5478 valid boards. See my script here: https://news.ycombinator.com/item?id=38266987 https://news.ycombinator.com/item?id=38266987
- deleted 3y ago[deleted]
- cantSpellSober 3y ago> It all started when Chrome implemented popovers in HTML [...] we found some pretty cool vectors that allow you to exploit hidden inputs and meta tags So if these vectors/sploits were patched out, the game wouldn't work anymore? (Impressive, thanks for sharing!)
- couchand 3y agoI'm not sure I agree that there's any exploit here. The crux of the claim seems to be that JavaScript code in an onbeforetoggle attribute is "unlikely to be filtered by a WAF". In any case, this game doesn't involve any of that, it just uses popovers as fancy internal links.
- forgotpwd16 3y agoExploit in this case simply means making use of something rather a security vuln.
- zamadatix 3y agoHN lunch challenge: Many here have noted one should be able to do this with far fewer total states by ignoring the order of the moves and focusing only on what the next board state needs to be. Who can generate the smallest working HTML file first? Preferably with how they generated the HTML too.
- abecedarius 3y agokragen made something like this decades ago, except it was one HTML page per state. Some code I wrote to generate a small table using BDDs is at https://codewords.recurse.com/issues/four/the-language-of-choice https://codewords.recurse.com/issues/four/the-language-of-ch... Also from there: > In a 6th-grade science fair Steve Wozniak did [a tic-tac-toe machine] much better: “about 100 transistors and about 100 diodes.” How? Beats me!
- p4bl0 3y agoI got 560KB. More than 300 times smaller. See my comment here: https://news.ycombinator.com/item?id=38266987 https://news.ycombinator.com/item?id=38266987
- p4bl0 3y agoI got down to 412KB! https://gist.github.com/p4bl0-/abf4960f07045d7a443230a46e73b849 https://gist.github.com/p4bl0-/abf4960f07045d7a443230a46e73b...
- p4bl0 3y agoAnd now to 367KB! By removing quotes around HTML attributes ^_^… https://gist.github.com/p4bl0-/abf4960f07045d7a443230a46e73b849#file-ttt_smallerer-py https://gist.github.com/p4bl0-/abf4960f07045d7a443230a46e73b...
- p4bl0 3y agoThis Python scripts generates a playable HTML-only Tic Tac Toe game. The generated file is 560KB, that is more than 300 times smaller. Also it works in any browser not just Chrome, probably even TUI browsers like w3m or links for that matter ^^. It generates all and only the valid game states, that is 5478 boards. It may be optimized further. Play it here: https://pablo.rauzy.name/dev/ttt.html https://pablo.rauzy.name/dev/ttt.html from copy import deepcopy opponent = {'X':'O','O':'X'} generated_boards = [] def board_id (board): return ''.join([''.join(row) for row in board]) def winning (board, player): return player == board[0][0] == board[0][1] == board[0][2] \ or player == board[1][0] == board[1][1] == board[1][2] \ or player == board[2][0] == board[2][1] == board[2][2] \ or player == board[0][0] == board[1][0] == board[2][0] \ or player == board[0][1] == board[1][1] == board[2][1] \ or player == board[0][2] == board[1][2] == board[2][2] \ or player == board[0][0] == board[1][1] == board[2][2] \ or player == board[0][2] == board[1][1] == board[2][0] def full (board): return '_' not in [cell for row in board for cell in row] def print_board (board, player): print(f'<hr id="{board_id(board)}">', end="") links = True if winning(board, opponent[player]): links = False print("WIN:") elif full(board): links = False print("DRAW:") for row in range(0, 3): for col in range(0, 3): if links and board[row][col] == '_': board[row][col] = player print(f'<a href="#{board_id(board)}">_</a>', end="") board[row][col] = '_' else: print(f'{board[row][col]}', end="") if row != 2: print('') return links def next_boards (board, player): boards = [] for row in range(0, 3): for col in range(0, 3): if board[row][col] == '_': board[row][col] = player bid = player + board_id(board) if bid not in generated_boards: boards.append(deepcopy(board)) generated_boards.append(bid) board[row][col] = '_' return boards def print_boards (board, player): if not print_board(board, player): return for board in next_boards(board, player): print_boards(board, opponent[player]) print("<pre>") print_boards([['_' for _ in range(0, 3)] for _ in range(0, 3)], 'X')
- 3y ago
- rabbits_2002 3y agothere arent that many states couldnt you do this a lot easier with hyperlinks