Totally Blind Chess

107

24

In this challenge, you play chess without seeing any of your opponent's pieces or moves. Or your own pieces. Or whether your own moves succeeded. You send only a stream of moves, with no feedback. If your move is legal (when it is your turn) it will be played, otherwise it is silently discarded.

I/O

The only input is two command line arguments. The 1st is either w or b, indicating whether you play White or Black. The 2nd is an integer in the range [0, 263), which you may use as a random seed. For a given seed, your program must produce deterministic output.

Your output must be an infinite stream of move attempts, one per line, in the format <start square> <end square> [optional piece for pawn promotion]. Squares are specified in algebraic notation. The 3rd parameter may be one of q r b n, for queen, rook, bishop, or knight respectively. Castling is performed by specifying the start and end locations of the king. If the 3rd parameter is not provided for a pawn promotion, queen is chosen by default. If the 3rd parameter is provided for a non-promotion, it is ignored. Examples:

  • b2 c4 (a possible knight move)
  • e3 d5 q (another possible knight move)
  • e2 e1 b (a possible promotion of a black pawn to bishop, or a king, rook, or queen move of either color)
  • g7 h8 (a possible capture by a white pawn which promotes to queen, or a bishop, queen, or king move of either color)
  • a8 f1 (a move attempt which always fails)

Check out the example bot for clarification on the I/O formats.

Any illegal move attempts will be skipped. Note that it is illegal to leave your king in check. When it is your turn, the controller will keep reading lines until it finds a valid move. This means that all games will be valid according to the rules of chess.

Limits

  • The game shall be declared a draw if both players complete 100 consecutive moves without captures or pawn moves.
  • A player who makes 2000 consecutive unsuccessful move attempts shall forfeit the game.
  • Players must output move attempts reasonably quickly, say no more than 10 ms per move attempt. There is no hard limit for this; ask me in The Nineteenth Byte if you are in doubt.
  • Your program must be runnable with free (lunch) software on at least one of Windows or Linux.

Controller

To download the controller (so far tested on Windows and Ubuntu),

git clone https://github.com/feresum/totallyblindchess.git

The repository is periodically updated to include the source code and configuration for all the players in the contest. See the README for usage instructions.

Victory condition

A round robin tournament where each pair of opponents play 200 games. Players score 2 points for a win and 1 point for a draw. Most points wins.

Final standings

The controller seed was 6847095374473737716.

================Standings after 100 cycles:=================
  Pokey                 3003
  BlindMoveMaker1       2412
  Prickly               2268
  Backline              2069
  ZombieMarch           1990
  JustEverything        1688
  Lichess2013-2015      1625
  Memorizer             1598
  BluntInstrument        738
  Scholar                609
============================================================

Congratulations to Brilliand with Pokey, scoring 83%.

Miscellaneous

Sample games from an old tournament

Although the official winner has been declared, you may, if you wish, post new answers with your score against the other participants (the controller repository includes all bots which competed).

feersum

Posted 2019-10-29T10:44:49.450

Reputation: 29 566

Normal Chess rules, so you have to checkmate your opponent? – Neil – 2019-10-29T13:28:03.617

9Similar to @Neil's question, do normal check rules apply despite no feedback (the only valid move when you are in check is to get out of check, it is illegal to move into check, etc)? Or do you just "play through" and victory is via actually capturing the king? (Seems to me that an inadvertent capture of the king is much more likely than a true checkmate in this format, so might be more practical.) – BradC – 2019-10-29T13:35:49.973

3Is a threefold repetition a guaranteed draw? – 79037662 – 2019-10-29T13:45:39.270

5What about partially allowed moves? E.g. if I specify moving a rook "through" an enemy piece, will that move be skipped or will my rook capture the enemy piece and stop there? – Adám – 2019-10-29T14:36:13.343

@Neil Yes, unless they forfeit for one of the possible reasons (the full list of ways the game can be decided can be found in the controller README). – feersum – 2019-10-29T17:01:29.213

@BradC Yes, check rules apply and it is illegal to move into check. Added clarification to the question. – feersum – 2019-10-29T17:02:12.417

2@79037662 No, threefold repetition is not enforced and cannot be claimed. Only the 100-move rule. – feersum – 2019-10-29T17:02:46.120

2@Adám No, there are no partial moves. – feersum – 2019-10-29T17:03:07.093

any language restrictions? – OganM – 2019-10-29T20:30:44.077

2@OganM No, just Your program must be runnable with free (lunch) software on at least one of Windows or Linux. – feersum – 2019-10-29T23:51:21.127

Cool. Any sample runs that we can copy the PGN notation to see how it plays? – justhalf – 2019-10-30T06:47:27.017

@justhalf You can run controller.py fight --move-log=<filename> to save notation from the games to <filename>. – feersum – 2019-10-30T07:37:25.477

Are stateful moves checked for legality? For example, en passant only on the subsequent move, castling through check or after a rook or king has been moved, etc. – MooseBoys – 2019-10-30T07:40:04.030

1@MooseBoys Yes, all the rules are enforced. – feersum – 2019-10-30T08:17:52.917

2Was thinking this might be interesting to see how good machine learning can get at this. But then realised that really any produced sequence loses very easily to some other specific sequence.

So while training itself you'll just get this endless recursion of specific counterplay sequences – Cruncher – 2019-10-30T21:00:49.643

2@Cruncher You want your bot to produce a random distribution of sequences, not something that's the same a every time. It's all about your distribution being better than the other guy's distribution. – feersum – 2019-10-30T23:44:23.767

Do we get pinged with colour and seed every turn or do both sides submit a move list once and impossible/illegal ones are removed until the list(s) are exhausted or the game legally ended? – Jan – 2019-10-31T09:56:07.763

1@feersum Given that it's blind, there's literally 0 input to give to the machine learning though. And whatever strategy you could possibly come up with will always be extremely susceptible to counter play. There's a delta of randomness here. To be uncounterable you need maximum randomness (see Just Everything). But there's no strategy. As soon as you have strategy it's less random and thus counterable. The extremes "Exact moveset" and "fully random" both have flaws, and all points in between do as well – Cruncher – 2019-10-31T13:44:21.620

1I just want to say that this is a really interesting idea, and I'm eagerly waiting for the tournament. – Sopel – 2019-10-31T13:46:16.047

3@justhalf I added a link to the notation of some sample games. – feersum – 2019-10-31T16:34:54.137

I observed Blunt Instrument moving pieces away from the enemy king, which is obviously cowardice. If we want to make improvements, should we post new answers or update our existing ones? – ymbirtt – 2019-10-31T17:42:48.707

@ymbirtt You can do it either way. I recommend basing your decision on whether the intended strategy changes; new strategy=new bot, bugfix/minor tweak=update answer. (Blunt Instrument being a coward sounds like a bug to me.) – Brilliand – 2019-10-31T21:55:02.573

@feersum Thanks! After removing the names and the "B f" in front, I can see the match here: http://www.caissa.com/chess-tools/pgn-editor.php

– justhalf – 2019-11-01T02:25:38.773

What are the rules on stalemate? Is it counted as draw, win, half-win, loss, illegal, forfeited move? – AkselA – 2019-11-01T09:31:56.973

@AkselA Stalemate is counted as a draw. Each player gets 1 point, as opposed to 2 for a win or 0 for a loss. – Brilliand – 2019-11-01T18:04:14.430

@feersum, Blunt Instrument v1 has been summarily dismissed for gross cowardice. I've put an updated version in my answer. – ymbirtt – 2019-11-01T20:31:53.480

1Until when can I submit a bot? – Pedro A – 2019-11-01T22:26:26.213

@PedroA I'll give at least a week's notice before when I decide to declare the winner. – feersum – 2019-11-01T23:49:58.413

@feersum I think you should add what you just said to the question – Pedro A – 2019-11-02T00:08:22.507

Reminds me of the framework that Tom7 used for a recent SIGBOVIK talk and YouTube video, except in that framework the AI is slightly less blind (it gets to see which squares are occupied, but not pieces or colors) and it produces a list of moves every turn, and the first legal move in the list is the one that's accepted. – hobbs – 2019-11-02T00:10:43.473

1A week's notice isn't much time to finish a complicated bot, especially if it isn't a holiday week. On the subject of finishing complicated bots, please take a look at my pull request on github. – Peter Taylor – 2019-11-02T10:24:26.200

1@PeterTaylor OK, I'll do 2 weeks. Also, to anyone who is still working on a bot before the deadline, you can ask me to extend it. – feersum – 2019-11-02T12:29:52.133

Answers

13

Pokey

Opens with the knight-based variant of the Scholar's Mate (a 5-move checkmate). If this fails, it presses the attempt a little farther, with a sequence of moves that hardcounters Prickly.

The structure of this bot is based on Prickly, but it improves on the Zombie March phase by frequently inserting king moves to get out of check, improves on the Just Everything idea by ordering the moves in a way that makes long-range moves more likely, and throws in a bit of Backline behavior right after the checkmate attempt. The queen swarm idea is still in there too, but that part is still failing.

#! /usr/bin/python

import sys
import random
import math

_, color, seed = sys.argv[:3]

random.seed(seed)

colnames = "abcdefgh"
rownames = "12345678" if color == "w" else "87654321"

def coord2code((col, row)):
    return colnames[col] + rownames[row];

def sendmove((a, b)):
    print coord2code(a), coord2code(b)

def long_safe_move(start, step, length):
    a,b = start
    x,y = step
    i = 0
    while i < length:
        m_start = (a+x*i,b+y*i)
        j = length
        while j > i:
            m_end = (a+x*j,b+y*j)
            if m_end[0] >= 0 and m_end[0] <= 7 and m_end[1] >= 0 and m_end[1] <= 7:
                yield (m_start, m_end)
            j -= 1
        i += 1

captures = ([((x,1),(x+1,2)) for x in range(7)]
         + [((x+1,1),(x,2)) for x in range(7)]
         + [((0,0),(0,1)), ((1,0),(3,1)), ((2,0),(1,1)), ((2,0),(3,1))]
         + [((7,0),(7,1)), ((6,0),(4,1)), ((5,0),(6,1)), ((5,0),(4,1))]
         + [((3,0),(2,1)), ((3,0),(3,1)), ((3,0),(4,1)), ((4,0),(5,1))])
sendmove(((4,1),(4,2)))
captures = ([m for m in captures if not (4,1) in m]
         + [((x,2),(x+1,3)) for x in range(7)]
         + [((x+1,2),(x,3)) for x in range(7)])
for m in captures:
    sendmove(m)
sendmove(((3,0),(5,2)))
captures = ([m for m in captures if not (3,0) in m and not m[0] == (5,2)]
         + [((4,0),(3,1))])
for m in captures:
    sendmove(m)
sendmove(((6,0),(7,2)))
captures = ([m for m in captures if not (6,0) in m]
         + [((4,0),(3,1))])
for m in captures:
    sendmove(m)
sendmove(((7,2),(6,4)))
captures = (captures
         + [((5,2),(5,6))])
for m in captures:
    sendmove(m)
sendmove(((7,1),(7,3)))
sendmove(((7,1),(7,2)))
sendmove(((7,2),(7,3)))
captures = ([m for m in captures if not (7,1) in m and not (7,2) in m]
         + [((7,0),(7,3))]
         + [((x,3),(x+1,4)) for x in range(7)]
         + [((x+1,3),(x,4)) for x in range(7)])
for m in captures:
    sendmove(m)
sendmove(((7,3),(7,4)))
captures = ([m for m in captures if not (7,3) in m]
         + [((7,0),(7,6))]
         + [((x,4),(x+1,5)) for x in range(7)]
         + [((x+1,4),(x,5)) for x in range(7)])
for m in captures:
    sendmove(m)
sendmove(((7,4),(7,5)))
captures = ([m for m in captures if not (7,4) in m]
         + [((x,5),(x+1,6)) for x in range(7)]
         + [((x+1,5),(x,6)) for x in range(7)])
for m in captures:
    sendmove(m)
sendmove(((7,5),(7,6)))
for m in long_safe_move((7,0), (0,1), 6):
    sendmove(m)
captures = ([m for m in captures if not (7,5) in m and not (5,6) in m]
         + [((x,6),(x+1,7)) for x in range(7)]
         + [((x+1,6),(x,7)) for x in range(7)])
for m in captures:
    sendmove(m)
sendmove(((5,2),(7,4)))
sendmove(((7,4),(7,6)))
captures = ([m for m in captures if not (7,4) in m]
         + [((6,4),(7,6))])
for m in captures:
    sendmove(m)
sendmove(((7,6),(7,7)))
captures = [m for m in captures if not (7,6) in m]
for m in captures:
    sendmove(m)
sendmove(((5,6),(6,5)))
captures = [m for m in captures if not (5,6) in m]
for m in captures:
    sendmove(m)
sendmove(((6,5),(7,6)))
sendmove(((7,6),(7,7)))
for m in captures:
    sendmove(m)
for m in long_safe_move((7,7), (-1,0), 7):
    sendmove(m)
for m in captures:
    sendmove(m)
for m in long_safe_move((7,6), (-1,0), 7):
    sendmove(m)
for m in captures:
    sendmove(m)
sendmove(((5,2),(3,0)))
sendmove(((7,4),(3,0)))
def zombiemarch():
    colorder = list(range(8))
    random.shuffle(colorder)
    roworder = [6,5,4,3,2,1]
    for col in colorder:
        for row in roworder:
            if col >= 1:
                yield ((col,row), (col-1,row+1))
            if col >= 1:
                yield ((col,row), (col-1,row+1))
            yield ((col,row), (col,row+1))
captures = list(zombiemarch())
for m in captures:
    sendmove(m)
captures = [m for m in captures if not m[0][1] == 1]
def jitter(tiles):
    fromset = set()
    for (a,b) in tiles:
        fromset.add(b)
    for (a,b) in fromset:
        if a>0:
            yield ((a,b), (a-1,b))
        if a<7:
            yield ((a,b), (a+1,b))
        if a>0:
            if b>0:
                yield ((a,b), (a-1,b-1))
            if b<7:
                yield ((a,b), (a-1,b+1))
        if a<7:
            if b>0:
                yield ((a,b), (a+1,b-1))
            if b<7:
                yield ((a,b), (a+1,b+1))
        if b>0:
            yield ((a,b), (a,b-1))
        if b<7:
            yield ((a,b), (a,b+1))
kingescape = list(jitter({((4,0),(4,0))}))
for m in captures:
    sendmove(m)
for m in captures:
    sendmove(m)
for m in kingescape:
    sendmove(m)
kingescape = list(jitter(kingescape))
for m in captures:
    sendmove(m)
for m in captures:
    sendmove(m)
for m in kingescape:
    sendmove(m)
kingescape = list(jitter(kingescape))
for m in captures:
    sendmove(m)
for m in captures:
    sendmove(m)
for m in kingescape:
    sendmove(m)
kingescape = list(jitter(kingescape))
for m in captures:
    sendmove(m)
for m in captures:
    sendmove(m)
for m in kingescape:
    sendmove(m)
for m in long_safe_move((7,7), (-1,0), 7):
    sendmove(m)
for m in captures:
    sendmove(m)
sendmove(((0,7),(2,5)))
for i in range(2):
    for m in long_safe_move((0+3*i,6), (1,0), 3):
        sendmove(m)
    for m in long_safe_move((1+3*i,7), (1,0), 3):
        sendmove(m)
    for m in long_safe_move((2+3*i,5), (1,0), 3):
        sendmove(m)
    kingescape = list(jitter(kingescape))
    for m in kingescape:
        sendmove(m)
sendmove(((7,7),(6,6)))
for m in long_safe_move((7,0), (0,1), 5):
    sendmove(m)
for i in range(3):
    for m in long_safe_move((6-2*i,6), (0,-1), 2):
        sendmove(m)
    for m in long_safe_move((7-2*i,5), (0,-1), 2):
        sendmove(m)
kingescape = list(jitter(kingescape))
for m in kingescape:
    sendmove(m)

def allmovegroups():
    # Knight moves
    for row in range(8):
        for col in range(8):
            for x in (1, 2, -2, -1):
                if x+col >= 0 and x+col <= 7:
                    for y in (2/x, -2/x):
                        if y+row >= 0 and y+row <= 7:
                            yield [((col, row),(x+col, y+row))]
                        else:
                            # Move knights away from edges
                            yield [((col, row),(int(math.copysign(x,4-col))+col, int(math.copysign(y,4-row))+row))]
    # Bishop moves
    for i in range(8):
        yield long_safe_move((0,i), (1,1), 7)
        yield long_safe_move((7,i), (-1,1), 7)
        yield long_safe_move((0,i), (1,-1), 7)
        yield long_safe_move((7,i), (-1,-1), 7)
        if i != 0:
            yield long_safe_move((i,0), (1,1), 7)
            yield long_safe_move((i,7), (1,-1), 7)
        if i != 7:
            yield long_safe_move((i,0), (-1,1), 7)
            yield long_safe_move((i,7), (-1,-1), 7)
    # Rook moves
    for i in range(8):
        yield long_safe_move((0,i), (1,0), 7)
        yield long_safe_move((7,i), (-1,0), 7)
        yield long_safe_move((i,0), (0,1), 7)
        yield long_safe_move((i,7), (0,-1), 7)

movegrouplist = [a for a in allmovegroups()]
random.shuffle(movegrouplist)

def allmoves():
    for movegroup in movegrouplist:
        for move in movegroup:
            yield move
movelist = list(allmoves())

while True:
    for (a, b) in movelist:
        print coord2code(a), coord2code(b)

Brilliand

Posted 2019-10-29T10:44:49.450

Reputation: 1 166

25

Just Everything

Generates a list of every possibly legal move, shuffles it, then cycles through it repeatedly.

Since there are only 1792 possibly legal moves, this will never forfeit due to the 2000-attempt rule.

This is meant as a template that other answers can build on.

#! /usr/bin/python

import sys
import random

_, color, seed = sys.argv[:3]

random.seed(seed)

colnames = "abcdefgh"
rownames = "12345678" if color == "w" else "87654321"

def coord2code((col, row)):
    return colnames[col] + rownames[row];

def buildmoves((col, row)):
    # Knight moves
    for x in (1, 2, -2, -1):
        if x+col >= 0 and x+col <= 7:
            for y in (2/x, -2/x):
                if y+row >= 0 and y+row <= 7:
                    yield (x+col, y+row)
    # Bishop moves
    for x in range(1,8):
        if col+x <= 7:
            if row+x <= 7:
                yield (col+x, row+x)
            if row-x >= 0:
                yield (col+x, row-x)
        if col-x >= 0:
            if row+x <= 7:
                yield (col-x, row+x)
            if row-x >= 0:
                yield (col-x, row-x)
    # Rook moves
    for x in range(1,8):
        if col+x <= 7:
            yield (col+x, row)
        if col-x >= 0:
            yield (col-x, row)
        if row+x <= 7:
            yield (col, row+x)
        if row-x >= 0:
            yield (col, row-x)

def allmoves():
    for row in range(8):
        for col in range(8):
            for to in buildmoves((row, col)):
                yield ((row, col), to)

movelist = [(coord2code(a), coord2code(b)) for (a,b) in allmoves()]
random.shuffle(movelist)

while True:
    for (a, b) in movelist:
        print a, b

Brilliand

Posted 2019-10-29T10:44:49.450

Reputation: 1 166

Do you mind if I steal your code for generating every legal move? – ymbirtt – 2019-10-30T14:54:57.120

Does this shuffle just once at the very beginning? Or does it shuffle between each pass through the list? – BradC – 2019-10-30T14:57:48.510

@BradC once - it cycles through a shuffled list (random.shuffle occurs once before the infinite while loop). – Jonathan Allan – 2019-10-30T15:19:06.633

1@ymbirtt Go right ahead, everyone is welcome to use this as a template. – Brilliand – 2019-10-30T20:39:41.090

2"Since there are only 1792 possibly legal moves, this will never forfeit due to the 2000-attempt rule." This just isn't true. It's just highly unlikely that it forfeits. For example, consider the case where only 1 of the 1792 were possible in your game state and it happens to be the last one. The opponent, and you, skip the next 1791 turns becuase your opponent's code is silly. On their 1792nd turn they make a move that makes your one move impossible (may have made other moves possible, but not the point). You then skip. Then they move back and you skip another 1700 moves. – Cruncher – 2019-10-30T20:54:47.897

12@Cruncher Sending an invalid move doesn't skip your turn. It stays your turn (with the opponent doing nothing) until you either come up with a legal move, or forfeit. – Brilliand – 2019-10-30T21:01:44.147

2@Brilliand Ah, I misunderstood. Thanks – Cruncher – 2019-10-30T21:04:30.097

21

Zombie March

Slowly walks all its pieces forward across the board, in a random order (but favoring pawns).

The first 5 moves sent specifically counter the scholar's mate.

#! /usr/bin/python

import sys
import random

_, color, seed = sys.argv[:3]

random.seed(seed)

moveorder = [(2, 2), (1, 1), (0, 2), (0, 1), (1, 2), (2, 1), (2, 0), (1, 0)]
moveorder7 = [(4, 0), (3, 0), (2, 0), (1, 0), (0, -4), (0, -3), (0, -2), (0, -1), (4, -4), (3, -3), (2, -2), (1, -1), (1, -2), (2, -1)]
colorder = random.sample([2, 3, 4, 5], 4) + random.sample([0, 1, 6, 7], 4)
roworder = [1, 2, 3, 4, 5, 6, 7, 0]

colnames = "abcdefgh"
rownames = "12345678" if color == "w" else "87654321"

def buildmoves((col, row), (x, y)):
    if row+y > 7 or row+y < 0:
        return
    if x == 0:
        yield (col, row+y)
        return
    if col < 4:
        if col+x <= 7:
            yield (col+x, row+y)
        if col-x >= 0:
            yield (col-x, row+y)
    else:
        if col-x >= 0:
            yield (col-x, row+y)
        if col+x <= 7:
            yield (col+x, row+y)

def coord2code((col, row)):
    return colnames[col] + rownames[row];

# Some fixed behavior (counter foolsmate)
print coord2code((6, 1)), coord2code((6, 2))
print coord2code((4, 1)), coord2code((4, 3))
print coord2code((3, 1)), coord2code((3, 3))
print coord2code((6, 2)), coord2code((7, 3))
print coord2code((3, 3)), coord2code((2, 4))

iter = 0
while True:
    iter += 1
    for row in roworder:
        for move in (moveorder if row*(1+iter*random.random()/10)<7 else random.sample(moveorder7, 8)):
            for col in colorder:
                for to in buildmoves((col, row), move):
                    print coord2code((col, row)), coord2code(to)

Brilliand

Posted 2019-10-29T10:44:49.450

Reputation: 1 166

An interesting variant, I think, could be alternate this method with some other method (other method could be 'prefer long moves'). – darune – 2019-10-31T10:10:56.463

16

Scholar

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

enum { WHITE, BLACK };

int main(int argc, char **argv)
{
    assert(argc == 3);
    int color;
    switch (argv[1][0])
    {
        case 'w': color = WHITE; break;
        case 'b': color = BLACK; break;
        default: assert(0);
    }
    if(color == WHITE) {
        printf("e2 e3\n");
        printf("d1 h5\n");
        printf("f1 c4\n");
        printf("h5 f7\n");
    }
    else {
        printf("e7 e6\n");
        printf("d8 h4\n");
        printf("f8 c5\n");
        printf("h4 f2\n");
    }
    srand(atoll(argv[2]));
    for ( ;; )
    {
        printf("%c%c %c%c\n", rand() % 8 + 'a', rand() % 8 + '1', rand() % 8 + 'a', rand() % 8 + '1');
    }
}

Scholar simply tries for a 4-move checkmate (with a 10% chance of a 2-move check that can result in a forfeit), then moves randomly after that. I tried adding in some nonrandom moves that were more likely to be legal, but at least in the naive way I did it that made the bot worse--more likely to forfeit when in check, I think.

histocrat

Posted 2019-10-29T10:44:49.450

Reputation: 20 600

Once I saw the answer to my comment, I thought of this as the first thing to try, including combining the moves of Scholar's Mate with those of Fool's Mate of course, just in case! – Neil – 2019-10-30T09:24:23.870

15

Blunt Instrument v2

There was a severe bug in the previous implementation that caused my bot to occasionally move pieces away from the enemy king. Given that the king is the most important piece, moving pieces away from him is obviously illogical. Now, any moves that lose too much ground are simply discarded. No retreat! No surrender!

Moves that lose a bit of ground are also thinned out, so that Blunt Instrument will spend less time contemplating cowardly moves that retreat from the king and more time punching stuff.

I've also switched from using Manhattan distance to Chebyshev, which I should really have used all along. Now, we measure distance as a number of kings' moves rather than rooks' moves. Granted, not every piece moves like the king, but I don't know what piece I'm moving so sod it. If my own king manages to punch a few pieces in the face while we play then so much the better.

Blunt Instrument

Inspired by Tom Murphy VII PhD's paper on high-performance chess algorithms, I've adapted his "swarm" strategy to this format. Swarm favours moves that put pieces as close to the enemy king as possible, since the king is the most important piece.

Since we don't actually know where the king is, we assume he stays where he is all game. Dodging is unsporting anyway. Stand still and take your punches, king!

Because we don't know whether any move has succeeded, I'll likely start out by making a bunch of pawn moves just to get them into the field, then probably throw the bishops out into the mid field and suicide them against the opposing pawns. I could probably do something more intelligent to do a sensible opening or whatever, but doing intelligent things deviates from the "playing chess with your fists" theme of my approach.

#! /usr/bin/python

import sys
import random

_, color, seed = sys.argv[:3]

random.seed(seed)

colnames = "abcdefgh"
rownames = "12345678" if color == "w" else "87654321"
ENEMY_KING = (4, 7)

def coord2code((col, row)):
    return colnames[col] + rownames[row];

def buildmoves((col, row)):
    # Knight moves
    for x in (1, 2, -2, -1):
        if x+col >= 0 and x+col <= 7:
            for y in (2/x, -2/x):
                if y+row >= 0 and y+row <= 7:
                    yield (x+col, y+row)
    # Bishop moves
    for x in range(1,8):
        if col+x <= 7:
            if row+x <= 7:
                yield (col+x, row+x)
            if row-x >= 0:
                yield (col+x, row-x)
        if col-x >= 0:
            if row+x <= 7:
                yield (col-x, row+x)
            if row-x >= 0:
                yield (col-x, row-x)
    # Rook moves
    for x in range(1,8):
        if col+x <= 7:
            yield (col+x, row)
        if col-x >= 0:
            yield (col-x, row)
        if row+x <= 7:
            yield (col, row+x)
        if row-x >= 0:
            yield (col, row-x)

def distance_to_square(coords1, coords2):
    x1, y1 = coords1
    x2, y2 = coords2
    return max(abs(x2-x1), abs(y2-y1))

def sort_key(move):
    from_, to_ = move
    # Our favourite moves are ones that land us on top of the enemy king
    # After that, we like moves that make us closer to the enemy king
    # After that, we like moves that take us a long way from where we started
    # After that, we like moves that move pieces that are a long way from the enemy king
    # After that, we pick at random!
    gained_ground = distance_to_square(from_, ENEMY_KING) - distance_to_square(to_, ENEMY_KING)
    return (distance_to_square(to_, ENEMY_KING), -gained_ground, -distance_to_square(from_, to_), -distance_to_square(from_, ENEMY_KING), random.randint(0, 999999))

def cowardly_filter(move):
    from_, to_ = move
    # Remove all moves that move more than 2 spaces away from the enemy king
    # Eliminate moves that gain no ground with probability 12/16
    # Eliminate moves that lose 1 space with probability 14/16
    # Eliminate moves that lose 2 spaces with probability 15/16
    # I pulled these numbers from my backside and don't know if they're actually good.

    gained_ground = distance_to_square(from_, ENEMY_KING) - distance_to_square(to_, ENEMY_KING)
    if gained_ground > 0:
        return True
    if gained_ground < -2:
        return False
    fudge_factor = random.randint(0, 16)
    # I tried to figure out a nice mathsy way of doing this but it's half past 8 and I want to play Dragon Age.
    if gained_ground == 0 and fudge_factor > 11:
        return True
    if gained_ground == -1 and fudge_factor > 13:
        return True
    if gained_ground ==  -2 and fudge_factor > 14:
        return True
    return False


def gen_all_valid_moves():
    for row in range(8):
        for col in range(8):
            for to in buildmoves((row, col)):
                yield ((row, col), to)

movelist = list(gen_all_valid_moves())

movelist.sort(key=sort_key)

# movelist = [(coord2code(a), coord2code(b)) for (a,b) in all_valid_moves]

while True:
    for (a, b) in filter(cowardly_filter, movelist):
        print coord2code(a), coord2code(b)

Thank you Brilliand for letting me shamelessly steal almost all your code.

ymbirtt

Posted 2019-10-29T10:44:49.450

Reputation: 1 792

2I haven't read (or run) your code, but man do I enjoy your style! – KlaymenDK – 2019-10-31T15:26:20.183

@Brilliand, yeah! I buggered that up, didn't I? I need to reject all cowardly moves. I'm also not sure what the back-and-forth thing comes from but I can have a look. – ymbirtt – 2019-10-31T23:17:48.207

I've been thinking that for an implementation that wants to pull both rooks and bishops toward a particular square, Euclidian distance (or square of Euclidian distance) might be best. Chebyshev distance has the weakness that rooks sometimes don't know how to get closer. – Brilliand – 2019-11-03T19:56:32.883

1I just ran a test tournament, and noticed that v2 of this has a tendency to forfeit when down to just its king. Specifically, it will move its king to where the enemy king should be, then forfeit because every possible move would put it farther away. – Brilliand – 2019-11-03T20:24:18.577

11

Lichess 2013-2015

I gathered move frequency data from about 50 million lichess games. Moves are ordered from the most to the least frequent. Moves are considered equal if the from square and the to square are equal. Promotion is assumed to always be to queen. I've chosen lichess because I have a lot of them sitting on my hard drive. I don't expect it to do well, it has nothing that is particularily tuned towards this challenge, but I'm curious how it will do.

all_moves = ['g1 f3 q', 'e2 e4 q', 'g8 f6 q', 'd2 d4 q', 'b1 c3 q', 'e1 h1 q', 'b8 c6 q', 'e8 h8 q', 'e7 e6 q', 'd7 d5 q', 'd7 d6 q', 'e7 e5 q', 'g7 g6 q', 'h2 h3 q', 'c7 c6 q', 'c2 c3 q', 'h7 h6 q', 'a7 a6 q', 'c7 c5 q', 'c2 c4 q', 'f8 e7 q', 'g2 g3 q', 'a2 a3 q', 'd2 d3 q', 'e2 e3 q', 'f2 f4 q', 'f7 f6 q', 'b7 b6 q', 'e4 e5 q','f2 f3 q', 'f3 e5 q', 'b2 b3 q', 'b8 d7 q', 'f1 e1 q', 'f1 c4 q', 'b7 b5 q', 'f1 e2 q', 'f8 g7 q', 'e4 d5 q', 'c1 e3 q', 'f6 e4 q', 'b1 d2 q', 'c8 b7 q', 'f8 e8 q', 'c5 d4 q', 'f1 d3 q', 'c1 g5 q', 'f7 f5 q', 'b2 b4 q', 'c8 d7 q', 'd4 d5 q', 'c8 g4 q', 'f3 d4 q', 'd1 d2 q', 'c4 d5 q', 'e6 e5 q', 'd4 e5 q', 'e6 d5 q', 'c3 d5 q', 'a2 a4 q', 'g2 g4 q', 'f6 d5 q', 'c6 d4 q', 'd6 e5 q', 'e5 d4 q', 'd8 d7 q', 'c1 d2 q', 'd8 e7 q', 'd1 e2 q', 'a7 a5 q', 'h2 h4 q', 'f1 g2 q', 'c8 e6 q', 'a1 d1 q', 'd5 e4 q', 'c6 c5 q', 'f8 d6 q', 'a8 c8 q', 'c1 b2 q', 'd6 d5 q', 'e7 f6 q', 'g8 e7 q', 'c1 f4 q', 'h7 h5 q', 'c3 e4 q', 'e5 e4 q', 'c6 e5 q', 'd8 c7 q', 'g7 g5 q', 'd5 d4 q', 'a8 d8 q', 'g1 h1 q', 'a1 c1 q', 'f8 c5 q', 'g7 f6 q', 'b7 c6 q', 'f4 e5 q', 'g8 g7 q', 'd1 f3 q', 'h4 h5 q', 'f3 g5 q', 'e3 e4 q', 'c3 c4 q', 'f4 f5 q', 'g5 f6 q', 'b2 c3 q', 'c6 d5 q', 'e1 a1 q', 'e3 d4 q','b5 b4 q', 'd3 e4 q', 'g8 h8 q', 'd3 d4 q', 'g6 g5 q', 'g4 g5 q', 'a8 b8 q', 'e2 f3 q', 'f3 f4 q', 'g4 f3 q', 'c8 f5 q', 'f8 b4 q', 'g2 f3 q', 'f1 b5 q', 'f6 f5 q', 'h3 h4 q', 'g1 g2 q', 'e8 a8 q', 'g3 g4 q', 'c3 d4 q', 'a1 b1 q', 'c5 c4 q', 'c4 c5 q', 'd1 c2 q', 'h5 h4 q', 'd5 c4 q', 'a5 a4 q', 'g5 g4 q', 'd8 f6 q', 'b4 b5 q', 'h6 h5 q', 'a6 a5 q', 'f5 f4 q', 'f6 e5 q', 'a4 a5 q', 'f7 e6 q', 'g1 e2 q', 'd7 c6 q', 'e7 d6 q', 'f6 g4 q', 'd4 c5 q', 'f1 d1 q', 'b4 c3 q', 'f5 e4 q', 'e8 e7 q', 'b5 c6 q', 'd8 d5 q', 'f8 d8 q', 'b6 b5 q', 'a1 e1 q', 'd1 d3 q', 'd7 e5 q', 'f2 e3 q', 'e2 d3 q', 'c4 b3 q', 'g1 f1 q', 'h8 g8 q', 'e5 f4 q', 'd1 d4 q', 'e1 e2 q', 'a3 a4 q', 'g1 h2 q', 'f3 e4 q', 'e8 d8 q', 'g8 f8 q', 'g1 f2 q', 'b3 b4 q', 'a8 e8 q', 'd1 e1 q', 'd7 f6 q', 'e5 f6 q', 'f6 d7 q', 'd8 e8 q', 'g8 h7 q', 'd8 b6 q', 'g8 f7 q', 'c3 e2 q', 'e6 f5 q', 'e1 d1 q', 'h6 g5 q','d2 c3 q', 'h1 g1 q', 'g5 h4 q', 'd3 c4 q', 'e4 f5 q', 'f8 f7 q', 'd2 f3 q', 'g4 h5 q', 'g7 h6 q', 'c3 b5 q', 'f1 f2 q', 'h5 g6 q', 'e3 f4 q', 'f6 h5 q', 'd8 d6 q', 'h3 g4 q', 'c4 b5 q', 'g5 f4 q', 'd6 c5 q', 'd2 e4 q', 'e5 e6 q', 'b5 c4 q', 'e8 f8 q', 'f7 g6 q', 'd5 d6 q', 'g4 f5 q', 'c1 b1 q', 'c6 e7 q', 'h4 g3 q', 'f3 h4 q', 'd4 d3 q', 'e5 d6 q', 'h7 g6 q', 'f3 d2 q', 'c4 d3 q', 'd8 c8 q', 'e1 f1 q', 'g6 f5 q', 'c8 b8 q', 'a6 b5 q', 'd2 e3 q', 'f6 g5 q', 'd7 c5 q', 'h5 h6 q', 'g2 h3 q', 'd7 e6 q', 'f2 g3 q', 'c6 b4 q', 'f4 g5 q', 'b4 c5 q', 'e7 f5 q', 'e4 e3 q', 'd5 c6 q', 'f4 g3 q', 'f5 g6 q', 'd1 b3 q', 'h4 g5 q', 'f3 g4 q', 'g3 f4 q', 'c7 d6 q', 'd1 c1 q', 'h5 g4 q', 'h2 g3 q', 'd5 e6 q', 'd4 c3 q', 'e4 f3 q', 'c6 a5 q', 'c5 b6 q', 'a3 b4 q', 'c2 d3 q', 'e4 f6 q', 'd1 d8 q', 'd3 e2 q', 'e8 d7 q', 'f3 g3 q', 'h4 h3 q', 'e7 g6 q', 'd7 b6 q', 'd1 h5 q', 'f5 f6 q','b6 c5 q', 'a4 a3 q', 'f4 f3 q', 'b3 c4 q', 'a5 a6 q', 'c5 b4 q', 'e5 f3 q', 'a4 b5 q', 'd8 d1 q', 'e2 g3 q', 'f5 g4 q', 'e7 d7 q', 'g5 g6 q', 'e8 f7 q', 'd2 c4 q', 'd4 c6 q', 'd6 e7 q', 'g4 g3 q', 'c4 c3 q', 'c5 c6 q', 'a5 b4 q', 'f4 e3 q', 'd3 d2 q', 'c8 c7 q', 'd8 a5 q', 'e7 g5 q', 'e2 d2 q', 'c6 b5 q', 'd6 d7 q', 'f6 g6 q', 'b5 a4 q', 'c7 b6 q', 'c3 a4 q', 'f5 e6 q', 'e2 f4 q', 'b4 b3 q', 'f8 g8 q', 'c5 d6 q', 'c1 c2 q', 'd3 c2 q', 'c2 b3 q', 'f8 c8 q', 'd4 e3 q', 'f6 e7 q', 'a1 f1 q', 'e3 d2 q', 'b5 b6 q', 'e4 d3 q', 'c3 b4 q', 'd4 f3 q', 'e6 e7 q', 'e3 e2 q', 'f3 e2 q', 'f1 g1 q', 'a8 f8 q', 'a4 b3 q', 'd7 e7 q', 'h1 h2 q', 'b7 a6 q', 'f7 e7 q', 'd2 e2 q', 'e7 c5 q', 'h6 g7 q', 'd7 c7 q', 'e5 c6 q', 'c8 d8 q', 'h8 h7 q', 'g6 h5 q', 'e1 d2 q', 'd5 f6 q', 'e7 f7 q', 'c8 a6 q', 'd2 b3 q', 'f1 c1 q', 'f2 e2 q', 'c6 c7 q', 'f3 e3 q', 'd1 d5 q', 'g3 h4 q', 'f6 f7 q','b8 a6 q', 'a5 b6 q', 'd8 d4 q', 'e7 d5 q', 'c1 d1 q', 'c3 c2 q', 'b4 a5 q', 'e6 d7 q', 'f3 f2 q', 'e2 f2 q', 'd2 c2 q', 'a6 a7 q', 'a3 a2 q', 'h8 f8 q', 'g8 h6 q', 'e7 d8 q', 'e5 c4 q', 'a2 b3 q', 'g7 f8 q', 'b3 c2 q', 'h6 h7 q', 'g5 e7 q', 'f1 f3 q', 'e4 d6 q', 'b2 a3 q', 'd8 h4 q', 'e2 d4 q', 'e4 c3 q', 'f6 g7 q', 'g5 h6 q', 'e1 e3 q', 'b1 a3 q', 'd6 c7 q', 'f6 e6 q', 'e1 f2 q', 'e3 f2 q', 'd5 c3 q', 'e7 f8 q', 'h7 h8 q', 'e2 c4 q', 'h1 e1 q', 'c7 d7 q', 'f7 g7 q', 'e2 g4 q', 'd1 g4 q', 'e5 d3 q', 'd1 a4 q', 'h8 e8 q', 'b6 b7 q', 'e5 d7 q', 'b6 c7 q', 'd8 g5 q', 'g7 g8 q', 'g6 g7 q', 'h3 h2 q', 'e4 c5 q', 'g5 e3 q', 'b3 b2 q', 'e3 f3 q', 'h2 h1 q', 'e3 d3 q', 'd4 f5 q', 'e6 f7 q', 'd3 e3 q', 'b7 d5 q', 'f8 f6 q', 'c7 b7 q', 'a7 b6 q', 'c2 d2 q', 'd5 f4 q', 'g3 f3 q', 'g7 e5 q', 'd1 d7 q', 'a8 a7 q', 'd8 f8 q', 'd3 f5 q', 'g7 f7 q', 'e7 e8 q', 'g3 g2 q', 'c4 e6 q','e3 g5 q', 'e7 c6 q', 'f7 f8 q', 'h1 f1 q', 'e3 c5 q', 'd7 d8 q', 'e5 g4 q', 'd3 c3 q', 'f2 g2 q', 'e4 g5 q', 'd7 e8 q', 'e1 e4 q', 'g5 e6 q', 'e6 d6 q', 'd6 c6 q', 'd1 f1 q', 'g4 h3 q', 'd1 d6 q', 'g2 f1 q', 'b3 a4 q', 'e5 g6 q', 'g5 f3 q', 'd8 d2 q', 'e2 d1 q', 'e1 e8 q', 'h3 g2 q', 'b8 c8 q', 'e1 e5 q', 'e6 f6 q', 'c2 b2 q', 'g2 f2 q', 'b6 a5 q', 'e8 e6 q', 'a2 a1 q', 'g6 f6 q', 'f3 g2 q', 'e7 h4 q', 'a7 a8 q', 'b8 b7 q', 'a1 a2 q', 'b5 d7 q', 'g2 g1 q', 'd6 e6 q', 'f2 f1 q', 'e8 e1 q', 'e2 e1 q', 'b1 c1 q', 'c7 c8 q', 'g3 f2 q', 'd2 d1 q', 'd7 b5 q', 'f3 h2 q', 'g6 f7 q', 'b7 e4 q', 'd2 f4 q', 'd5 e7 q', 'd3 b5 q', 'e4 g3 q', 'f4 d6 q', 'e2 f1 q', 'g4 e3 q', 'd5 e3 q', 'e1 e7 q', 'b1 b2 q', 'b7 c8 q', 'd6 f4 q', 'c1 a3 q', 'g4 e6 q', 'h8 d8 q', 'e8 e5 q', 'f5 d3 q', 'c2 c1 q', 'c6 d7 q', 'e4 d2 q', 'd4 e6 q', 'g4 f6 q', 'h8 g7 q', 'c5 e3 q', 'e7 b4 q', 'h5 f4 q','e2 c3 q', 'g4 e2 q', 'h1 d1 q', 'd7 f5 q', 'c4 f7 q', 'd7 c8 q', 'h7 g7 q', 'd8 d3 q', 'e2 h5 q', 'g1 h3 q', 'd5 e5 q', 'd4 e2 q', 'c1 h6 q', 'c5 e4 q', 'g7 h7 q', 'h1 g2 q', 'b7 b8 q', 'h7 g8 q', 'd2 e1 q', 'h2 g2 q', 'e6 c4 q', 'b5 d6 q', 'f6 e8 q', 'g3 h3 q', 'b8 a8 q', 'b2 b1 q', 'f7 e8 q', 'c3 d2 q', 'h2 g1 q', 'g4 e5 q', 'f4 g4 q', 'e5 d5 q', 'e4 f4 q', 'e4 d4 q', 'e8 e2 q', 'd2 g5 q', 'c4 e5 q', 'd4 e4 q', 'b4 d2 q', 'e2 b5 q', 'c4 e2 q', 'h5 f3 q', 'g5 e4 q', 'd4 c4 q', 'f4 e4 q', 'e1 e6 q', 'd2 b4 q', 'b2 d4 q', 'e5 f5 q', 'a5 c4 q', 'e8 e4 q', 'f6 h7 q', 'b1 a1 q', 'd3 g6 q', 'h4 f5 q', 'g2 h2 q', 'g6 h6 q', 'f5 e5 q', 'f5 g5 q', 'g4 f4 q', 'e3 h6 q', 'b6 c4 q', 'd5 c5 q', 'g6 f4 q', 'g5 f7 q', 'd2 c1 q', 'c6 b6 q', 'f6 d4 q', 'g4 h4 q', 'f7 g8 q', 'b2 a2 q', 'c8 c2 q', 'c5 d3 q', 'h3 g3 q', 'd4 b5 q', 'g3 f5 q', 'b6 d5 q', 'b7 f3 q', 'b7 a7 q', 'b5 d3 q','h5 g5 q', 'c3 d3 q', 'g2 e4 q', 'd7 g4 q', 'b6 c6 q', 'c2 e4 q', 'g5 f5 q', 'c7 d8 q', 'e6 g4 q', 'c6 d6 q', 'c7 e5 q', 'b7 c7 q', 'g7 d4 q', 'c4 d6 q', 'f8 b8 q', 'g5 h5 q', 'd5 b6 q', 'h4 g4 q', 'c6 b7 q', 'c1 c7 q', 'h6 g6 q', 'b3 d5 q', 'f1 f4 q', 'c3 b2 q', 'b4 d3 q', 'b2 c1 q', 'b2 c2 q', 'c3 b3 q', 'e5 f7 q', 'a6 b7 q', 'b5 c3 q', 'f8 f5 q', 'f1 b1 q', 'c4 e3 q', 'd7 f8 q', 'h5 f6 q', 'd6 b4 q', 'f2 e1 q', 'f5 d4 q', 'g7 h8 q', 'c5 e7 q', 'f3 d5 q', 'd4 b3 q', 'b2 e5 q', 'd5 b4 q', 'b3 c3 q', 'g6 e5 q', 'a4 c5 q', 'f3 e1 q', 'd8 b8 q', 'd5 c7 q', 'b5 a6 q', 'b4 d6 q', 'h4 f6 q', 'e1 c1 q', 'f5 e3 q', 'b6 d4 q', 'd5 d8 q', 'd2 f1 q', 'b4 a3 q', 'c8 c6 q', 'c5 e6 q', 'd4 c2 q', 'g3 e4 q', 'b4 c6 q', 'b3 c5 q', 'g6 h7 q', 'c8 h3 q', 'd1 b1 q', 'c2 d1 q', 'h6 f5 q', 'c7 e7 q', 'h4 f3 q', 'e8 e3 q', 'c1 c3 q', 'c4 d4 q', 'g3 e5 q', 'd8 a8 q', 'f4 d5 q', 'b8 d8 q','c1 e1 q', 'c8 e8 q', 'c8 c1 q', 'c5 d5 q', 'e8 c8 q', 'b5 c7 q', 'f2 g1 q', 'g3 h2 q', 'a3 b2 q', 'c2 e2 q', 'c5 f2 q', 'b6 a6 q', 'b1 d1 q', 'b8 b2 q', 'c4 a2 q', 'c1 c8 q', 'c4 b4 q', 'f4 d3 q', 'd2 h6 q', 'd1 a1 q', 'c8 c3 q', 'f8 h6 q', 'a7 b7 q', 'c8 c4 q', 'f5 e7 q', 'f3 h5 q', 'c5 b5 q', 'd6 g3 q', 'f5 d6 q', 'c3 d1 q', 'd1 g1 q', 'b7 a8 q', 'f4 e6 q', 'c7 b8 q', 'a5 c7 q', 'd8 g8 q', 'b2 f6 q', 'f1 f7 q', 'd4 d1 q', 'g5 d2 q', 'b4 e7 q', 'a2 b2 q', 'e4 f2 q', 'g4 d7 q', 'd4 f6 q', 'b1 b7 q', 'b3 a3 q', 'b3 d4 q', 'c6 d8 q', 'a6 c5 q', 'f3 h3 q', 'a5 c6 q', 'd2 f2 q', 'f1 f8 q', 'g6 e4 q', 'f8 a8 q', 'h4 e7 q', 'f1 f5 q', 'f6 h4 q', 'c6 e4 q', 'g2 d5 q', 'g4 f2 q', 'e7 c7 q', 'c2 b1 q', 'a3 c4 q', 'f1 f6 q', 'h4 g6 q', 'f8 f4 q', 'e2 c2 q', 'g2 h1 q', 'f1 a1 q', 'd5 f3 q', 'b4 c2 q', 'f4 d2 q', 'f4 e2 q', 'e3 b6 q', 'c5 d7 q', 'f8 f1 q', 'd3 h7 q', 'd7 f7 q','a8 a6 q', 'd3 f3 q', 'h2 g4 q', 'b6 b2 q', 'd7 b7 q', 'b4 c4 q', 'b5 d4 q', 'h5 g3 q', 'c8 c5 q', 'c1 c6 q', 'a5 b5 q', 'e3 g3 q', 'f8 h8 q', 'b2 a1 q', 'b6 d7 q', 'b4 d5 q', 'a4 b4 q', 'b1 a2 q', 'f3 f6 q', 'b1 c2 q', 'b8 a7 q', 'b5 c5 q', 'd2 b2 q', 'b5 e2 q', 'f8 f2 q', 'a4 c2 q', 'f8 f3 q', 'a8 g8 q', 'a4 c3 q', 'd4 d2 q', 'a6 b6 q', 'e4 e2 q', 'b3 a2 q', 'e5 g3 q', 'e4 c6 q', 'b4 a4 q', 'e2 e5 q', 'b8 c7 q', 'b5 a5 q', 'g7 c3 q', 'd6 e4 q', 'f3 d3 q', 'c4 d2 q', 'f3 d1 q', 'h3 f4 q', 'c1 c5 q', 'a1 a3 q', 'c3 e5 q', 'h6 g4 q', 'f4 h6 q', 'f5 h4 q', 'd6 f5 q', 'a6 c4 q', 'f3 c6 q', 'a3 b3 q', 'd7 h3 q', 'a1 g1 q', 'f6 c3 q', 'h5 e2 q', 'd7 a4 q', 'f4 c7 q', 'e5 g7 q', 'f5 d7 q', 'd5 d7 q', 'd5 a5 q', 'd3 e5 q', 'e5 c3 q', 'f6 d8 q', 'a6 c7 q', 'd3 f4 q', 'd5 b7 q', 'c1 c4 q', 'e3 f5 q', 'g6 e7 q', 'e4 g6 q', 'b1 e1 q', 'f6 f3 q', 'h3 g5 q', 'b8 b6 q', 'f6 b2 q','f4 h5 q', 'f3 b7 q', 'e6 g6 q', 'b3 b7 q', 'c8 a8 q', 'g4 h6 q', 'd5 b3 q', 'h5 f7 q', 'f1 h1 q', 'h6 f4 q', 'f5 c2 q', 'a6 b4 q', 'e7 g7 q', 'e7 e4 q', 'g3 h5 q', 'e3 d5 q', 'e6 h3 q', 'c7 a7 q', 'f1 h3 q', 'a1 a7 q', 'g3 e2 q', 'f6 f4 q', 'f3 f5 q', 'c8 f8 q', 'e5 e7 q', 'f5 h6 q', 'd2 a5 q', 'b3 e6 q', 'f3 f7 q', 'b1 b3 q', 'b8 e8 q', 'e4 c2 q', 'b6 a7 q', 'c6 b8 q', 'h7 g5 q', 'e6 f4 q', 'f6 h6 q', 'a5 b3 q', 'c7 d5 q', 'd4 b2 q', 'c2 a2 q', 'c2 f5 q', 'd1 h1 q', 'a8 a1 q', 'd6 f6 q', 'a4 c6 q', 'h8 c8 q', 'g5 h3 q', 'a8 a2 q', 'g5 d8 q', 'd6 c4 q', 'c1 f1 q', 'a3 c2 q', 'a5 c3 q', 'a2 b1 q', 'e5 c7 q', 'd8 h8 q', 'f4 h3 q', 'e6 d4 q', 'a1 a8 q', 'b3 d2 q', 'e6 b3 q', 'd4 b6 q', 'c4 b6 q', 'd3 c5 q', 'f4 g6 q', 'c6 f3 q', 'd5 f7 q', 'b6 d8 q', 'e4 g4 q', 'e5 g5 q', 'c1 a1 q', 'f5 g3 q', 'c7 a5 q', 'e2 g2 q', 'd3 a6 q', 'c7 f4 q', 'd4 f2 q', 'd6 d8 q', 'h6 e3 q','h8 h6 q', 'a6 d3 q', 'a3 b5 q', 'c5 b3 q', 'e3 g4 q', 'e4 b7 q', 'h4 f2 q', 'c2 e3 q', 'e1 g1 q', 'c2 f2 q', 'b7 g2 q', 'a8 a5 q', 'c7 f7 q', 'c2 a4 q', 'e1 b1 q', 'e4 g2 q', 'g8 g6 q', 'g6 h4 q', 'h6 f7 q', 'a1 a4 q', 'c7 e6 q', 'a5 c5 q', 'b6 e3 q', 'c2 d4 q', 'b2 g7 q', 'e3 a7 q', 'd3 b1 q', 'f6 d6 q', 'h5 e5 q', 'd4 g7 q', 'a4 b6 q', 'd3 b3 q', 'c7 a8 q', 'f6 g8 q', 'd3 d1 q', 'a3 c5 q', 'g7 b2 q', 'e7 b7 q', 'e5 b2 q', 'd6 h2 q', 'd3 g3 q', 'a4 c4 q', 'd4 f4 q', 'h1 h3 q', 'e2 e6 q', 'g4 d1 q', 'c6 a7 q', 'd6 b6 q', 'e8 g8 q', 'f4 h4 q', 'd2 d5 q', 'd3 f1 q', 'e2 b2 q', 'e3 c4 q', 'b5 b7 q', 'b6 b4 q', 'a7 b8 q', 'g2 c6 q', 'b4 b2 q', 'd3 d5 q', 'c3 f6 q', 'e6 g5 q', 'c5 a7 q', 'h2 f3 q', 'e8 b8 q', 'h3 f5 q', 'a7 c7 q', 'c3 b1 q', 'a8 h8 q', 'h1 c1 q', 'g1 g3 q', 'f5 h3 q', 'b3 d1 q', 'e5 e3 q', 'e6 c5 q', 'f2 d2 q', 'e3 e5 q', 'd5 f5 q', 'g3 d6 q', 'f7 d7 q','e2 e7 q', 'c5 c7 q', 'd6 f8 q', 'f5 h5 q', 'g6 d3 q', 'c7 c4 q', 'e5 c5 q', 'e7 c8 q', 'e5 e2 q', 'h4 f4 q', 'e3 c3 q', 'd5 d3 q', 'h5 f5 q', 'h3 e6 q', 'd6 d4 q', 'c3 a2 q', 'b6 d6 q', 'a1 a6 q', 'f4 f6 q', 'b8 b4 q', 'b7 d7 q', 'e2 a6 q', 'g3 e3 q', 'e7 a3 q', 'f4 h2 q', 'd7 d4 q', 'h8 h5 q', 'c2 g6 q', 'c3 e3 q', 'a1 h1 q', 'd6 b7 q', 'a2 c2 q', 'g5 g3 q', 'e4 e6 q', 'd7 a7 q', 'c4 c2 q', 'b8 b5 q', 'e3 c1 q', 'c4 a5 q', 'g5 e5 q', 'e6 c6 q', 'a8 b7 q', 'g4 g6 q', 'a8 a3 q', 'c6 a6 q', 'c2 a1 q', 'a8 a4 q', 'g4 e4 q', 'e8 f6 q', 'e4 c4 q', 'd4 d6 q', 'f5 f3 q', 'e6 e8 q', 'a1 a5 q', 'f4 f2 q', 'c3 a3 q', 'c5 a4 q', 'd6 f7 q', 'h7 f6 q', 'b1 f1 q', 'f5 f7 q', 'b8 f8 q', 'e1 g3 q', 'f7 e5 q', 'b3 d3 q', 'f1 g3 q', 'f2 d4 q', 'h6 f8 q', 'c6 e6 q', 'e7 e2 q', 'c4 b2 q', 'a3 d6 q', 'b3 b5 q', 'h5 h7 q', 'f6 f2 q', 'c5 b7 q', 'e3 e1 q', 'h4 e4 q', 'b2 d2 q', 'e6 a2 q','g2 b7 q', 'd2 a2 q', 'f8 g6 q', 'c4 a6 q', 'b1 b4 q', 'd5 g2 q', 'e6 f8 q', 'd4 b4 q', 'g6 e6 q', 'g3 g5 q', 'e8 g6 q', 'h3 f2 q', 'd5 b5 q', 'g5 h7 q', 'e4 h4 q', 'h8 h4 q', 'e5 h5 q', 'c6 a4 q', 'd2 g2 q', 'e4 e1 q', 'e6 e4 q', 'e2 c1 q', 'h3 f3 q', 'd2 d6 q', 'h5 h3 q', 'b8 b3 q', 'c7 c3 q', 'c7 b5 q', 'f7 d5 q', 'f7 h7 q', 'c5 a6 q', 'a1 b2 q', 'd5 d2 q', 'f4 d4 q', 'd3 b2 q', 'c4 e4 q', 'a5 d8 q', 'c5 e5 q', 'b1 b5 q', 'c4 a4 q', 'c7 c2 q', 'a6 e2 q', 'h1 h4 q', 'd7 g7 q', 'b1 b8 q', 'c3 a5 q', 'h4 h6 q', 'f3 c3 q', 'd4 a4 q', 'b8 b1 q', 'h1 h5 q', 'e6 c7 q', 'd5 d1 q', 'e7 e3 q', 'd4 d8 q', 'e3 f1 q', 'b4 a6 q', 'a6 c6 q', 'c5 a5 q', 'e5 e1 q', 'f7 d6 q', 'b1 b6 q', 'd4 d7 q', 'e6 c8 q', 'd2 d8 q', 'd6 b5 q', 'e4 e7 q', 'f5 g7 q', 'c6 c4 q', 'c4 c6 q', 'd3 f2 q', 'a4 d7 q', 'f3 g1 q', 'c7 g3 q', 'g8 g2 q', 'c4 a3 q', 'd7 b8 q', 'g8 e8 q', 'a3 c3 q', 'b5 a3 q','b5 a7 q', 'a5 d2 q', 'f2 h4 q', 'f1 e3 q', 'g8 g5 q', 'c2 c5 q', 'a2 d5 q', 'd6 a3 q', 'd3 b4 q', 'h5 g7 q', 'g1 e1 q', 'c5 c3 q', 'g6 g4 q', 'b3 f7 q', 'f2 e4 q', 'c4 c7 q', 'e5 e8 q', 'g6 f8 q', 'h1 h7 q', 'g4 g7 q', 'a5 a2 q', 'f7 h8 q', 'f2 h2 q', 'd7 d1 q', 'f5 d5 q', 'd6 g6 q', 'c6 a8 q', 'g1 g7 q', 'e3 c2 q', 'c2 c7 q', 'd2 d7 q', 'e8 d6 q', 'b7 e7 q', 'f7 g5 q', 'g5 g2 q', 'c6 c8 q', 'f2 c2 q', 'h6 f6 q', 'f8 e6 q', 'b7 c5 q', 'c3 c5 q', 'g5 c1 q', 'd6 b8 q', 'e1 f3 q', 'a7 d7 q', 'f7 c7 q', 'h8 a8 q', 'c2 b4 q', 'g1 g4 q', 'd1 e3 q', 'h4 h2 q', 'c3 c1 q', 'a5 a3 q', 'c6 e8 q', 'b6 a4 q', 'b4 d4 q', 'h8 h3 q', 'a4 a2 q', 'a5 a7 q', 'c5 f8 q', 'c4 f1 q', 'f4 g2 q', 'f5 h7 q', 'f4 f7 q', 'd4 g4 q', 'b2 c4 q', 'c2 c6 q', 'f1 a6 q', 'b6 f2 q', 'a2 c4 q', 'e7 e1 q', 'd3 d6 q', 'a6 c8 q', 'a3 e7 q', 'c6 g2 q', 'g5 g7 q', 'd7 d2 q', 'g3 f1 q', 'b2 e2 q', 'a6 a8 q','c5 c2 q', 'g3 g6 q', 'h8 h2 q', 'g4 h2 q', 'e2 e8 q', 'h8 b8 q', 'd7 d3 q', 'c3 g7 q', 'e1 d3 q', 'h1 h6 q', 'f3 f1 q', 'f8 a3 q', 'f2 d3 q', 'f7 h5 q', 'c5 a3 q', 'd3 d7 q', 'e6 g7 q', 'f6 f8 q', 'b3 a5 q', 'f6 c6 q', 'e3 h3 q', 'e6 e2 q', 'b6 b3 q', 'g4 g2 q', 'a4 a7 q', 'a4 a6 q', 'g8 g4 q', 'f4 c1 q', 'b4 a2 q', 'e3 e6 q', 'c3 a1 q', 'b4 b6 q', 'd5 a2 q', 'c3 e1 q', 'c3 c7 q', 'b5 d5 q', 'd3 d8 q', 'a5 b7 q', 'd6 d2 q', 'a7 b5 q', 'd6 c8 q', 'g7 f5 q', 'h1 a1 q', 'h6 d2 q', 'a2 d2 q', 'e7 a7 q', 'a3 a1 q', 'd6 d1 q', 'e4 e8 q', 'f3 b3 q', 'g8 d8 q', 'b3 b6 q', 'd5 h5 q', 'f7 f4 q', 'c3 f3 q', 'f2 g4 q', 'e3 e7 q', 'd6 d3 q', 'd8 e6 q', 'b5 b3 q', 'c6 c3 q', 'h7 f7 q', 'h3 f1 q', 'c3 c6 q', 'g3 g7 q', 'g1 d1 q', 'e2 a2 q', 'a4 d1 q', 'a8 c6 q', 'h3 h5 q', 'c6 c2 q', 'd4 h4 q', 'd4 a7 q', 'g1 g5 q', 'g6 g3 q', 'd6 a6 q', 'f5 f2 q', 'h1 h8 q', 'a5 d5 q', 'd5 g5 q','b7 d6 q', 'e4 h7 q', 'b7 f7 q', 'd2 b1 q', 'c2 g2 q', 'h6 h4 q', 'b2 f2 q', 'e8 c6 q', 'c7 g7 q', 'a7 d4 q', 'e5 h2 q', 'd3 a3 q', 'h1 b1 q', 'a6 f1 q', 'g4 c8 q', 'b6 b8 q', 'e6 e3 q', 'f2 f5 q', 'd5 a8 q', 'a7 e7 q', 'e8 c7 q', 'f5 c8 q', 'a3 c1 q', 'h4 g2 q', 'b3 e3 q', 'b4 b7 q', 'a7 c5 q', 'h8 h1 q', 'b2 d3 q', 'e3 g2 q', 'b6 e6 q', 'e1 h4 q', 'g3 c7 q', 'g8 g3 q', 'b6 c8 q', 'a2 b4 q', 'f2 b2 q', 'f3 a8 q', 'e7 h7 q', 'b5 b2 q', 'a4 b2 q', 'e8 h5 q', 'g6 c2 q', 'd3 c1 q', 'a4 d4 q', 'b3 b1 q', 'e6 d8 q', 'h4 d8 q', 'f2 c5 q', 'a5 e5 q', 'g1 g6 q', 'h3 d7 q', 'a7 c6 q', 'a1 c3 q', 'g7 e7 q', 'f7 b7 q', 'a2 e2 q', 'e6 e1 q', 'g3 d3 q', 'b1 d3 q', 'd8 c6 q', 'h2 f2 q', 'g2 f4 q', 'e1 c3 q', 'h3 h6 q', 'e3 d1 q', 'b1 e4 q', 'g6 g2 q', 'h5 d1 q', 'd3 h3 q', 'e7 g8 q', 'c6 f6 q', 'f7 f3 q', 'e6 h6 q', 'a2 e6 q', 'a7 f7 q', 'f2 f7 q', 'c8 g8 q', 'h8 f6 q', 'd4 a1 q','g3 e1 q', 'd6 e8 q', 'e3 b3 q', 'a2 f2 q', 'b5 f1 q', 'f2 f6 q', 'f4 b8 q', 'd1 c3 q', 'f8 d7 q', 'g6 e8 q', 'b7 b4 q', 'h2 e5 q', 'e3 e8 q', 'e2 h2 q', 'f5 b1 q', 'a3 a5 q', 'h6 h8 q', 'h7 e4 q', 'f6 h8 q', 'f7 d8 q', 'a6 d6 q', 'h5 h8 q', 'h2 f4 q', 'a7 e3 q', 'c1 g1 q', 'f7 f2 q', 'e6 b6 q', 'a6 a4 q', 'g2 e2 q', 'g4 d4 q', 'f4 f1 q', 'a8 d5 q', 'c5 c8 q', 'd3 e1 q', 'e5 h8 q', 'f6 a1 q', 'c4 c1 q', 'h3 e3 q', 'a2 c3 q', 'h4 h7 q', 'b7 b3 q', 'h6 h3 q', 'c7 c1 q', 'f7 h6 q', 'b2 b6 q', 'b5 e8 q', 'a7 a4 q', 'f5 f8 q', 'c2 c8 q', 'f7 c4 q', 'a2 a5 q', 'c8 d6 q', 'b2 b5 q', 'b4 f8 q', 'c4 f4 q', 'b4 e1 q', 'a3 d3 q', 'h7 f5 q', 'e2 g1 q', 'a1 d4 q', 'h4 d4 q', 'c7 e8 q', 'c8 h8 q', 'c7 a6 q', 'b3 c1 q', 'h3 h1 q', 'b7 b2 q', 'a3 f8 q', 'b3 f3 q', 'a5 a8 q', 'c1 d3 q', 'a4 a1 q', 'g7 e6 q', 'a8 e4 q', 'g5 d5 q', 'b8 d6 q', 'a4 e4 q', 'b8 e5 q', 'h5 d5 q', 'g6 d6 q','h7 d3 q', 'd2 h2 q', 'b4 e4 q', 'e4 b4 q', 'f4 c4 q', 'h6 e6 q', 'e5 b5 q', 'e4 b1 q', 'b2 b7 q', 'c3 g3 q', 'e1 c2 q', 'h4 e1 q', 'e5 a5 q', 'f6 b6 q', 'd7 h7 q', 'g6 h8 q', 'e4 a8 q', 'f1 d2 q', 'c1 h1 q', 'h4 h1 q', 'c5 f5 q', 'h5 e8 q', 'c4 c8 q', 'g7 g4 q', 'f2 h3 q', 'f2 h1 q', 'a1 e5 q', 'h5 h2 q', 'f3 h1 q', 'f3 f8 q', 'b5 e5 q', 'c8 e7 q', 'h7 e7 q', 'g8 c8 q', 'e5 b8 q', 'd1 f2 q', 'b6 f6 q', 'g7 a1 q', 'g2 g5 q', 'b8 g8 q', 'g2 e3 q', 'f5 c5 q', 'b2 g2 q', 'h3 h7 q', 'f2 d1 q', 'e5 a1 q', 'b5 b8 q', 'd8 f7 q', 'e4 a4 q', 'f6 f1 q', 'b1 g1 q', 'h1 f3 q', 'd6 h6 q', 'c5 c1 q', 'g6 g8 q', 'c2 e1 q', 'c3 c8 q', 'a2 g2 q', 'f2 a2 q', 'a8 c7 q', 'b7 g7 q', 'e8 g7 q', 'h7 h4 q', 'c2 a3 q', 'a6 a3 q', 'e4 h1 q', 'c8 b6 q', 'f7 a7 q', 'a7 g7 q', 'a3 a6 q', 'g1 c1 q', 'f4 f8 q', 'b4 b1 q', 'g1 g8 q', 'f5 f1 q', 'g7 d7 q', 'a6 e6 q', 'b8 h8 q', 'h6 c1 q', 'c4 g4 q','a3 e3 q', 'g7 g3 q', 'e6 a6 q', 'g8 g1 q', 'c4 g8 q', 'h2 e2 q', 'c6 c1 q', 'c6 g6 q', 'f7 f1 q', 'a7 a3 q', 'e3 g1 q', 'g2 d2 q', 'e3 a3 q', 'h2 f1 q', 'h7 f8 q', 'a5 a1 q', 'e8 b5 q', 'h2 d6 q', 'a6 a2 q', 'f7 b3 q', 'a3 a7 q', 'b6 a8 q', 'a2 a6 q', 'g3 g1 q', 'a6 b8 q', 'c5 g5 q', 'c2 h7 q', 'f2 b6 q', 'b1 h1 q', 'h8 e5 q', 'f2 f8 q', 'h8 f7 q', 'c1 e2 q', 'g3 c3 q', 'a4 a8 q', 'g2 g6 q', 'h2 h5 q', 'a8 f3 q', 'e1 b4 q', 'e6 g8 q', 'h3 d3 q', 'h5 c5 q', 'g7 c7 q', 'c7 h7 q', 'a1 c2 q', 'a5 f5 q', 'g2 c2 q', 'g2 a8 q', 'b1 f5 q', 'c1 b3 q', 'b3 g3 q', 'g3 h1 q', 'g4 c4 q', 'b4 f4 q', 'a7 a2 q', 'g8 a8 q', 'c2 h2 q', 'g5 c5 q', 'g7 h5 q', 'a7 h7 q', 'a2 a7 q', 'h6 h2 q', 'h7 d7 q', 'a3 f3 q', 'b4 b8 q', 'a4 f4 q', 'b7 a5 q', 'c7 h2 q', 'h1 e4 q', 'b2 b8 q', 'g1 a1 q', 'a2 h2 q', 'c4 h4 q', 'c5 h5 q', 'b3 a1 q', 'a1 f6 q', 'a5 g5 q', 'h2 d2 q', 'b2 a4 q', 'a5 h5 q','b7 b1 q', 'f3 a3 q', 'g8 b8 q', 'h7 c7 q', 'h3 c8 q', 'g6 c6 q', 'h4 c4 q', 'g7 g2 q', 'b6 g6 q', 'a8 b6 q', 'h4 h8 q', 'g2 b2 q', 'b5 b1 q', 'b3 b8 q', 'h2 c2 q', 'a3 b1 q', 'h7 b7 q', 'g1 b1 q', 'h6 d6 q', 'h7 h3 q', 'b5 f5 q', 'f8 h7 q', 'c3 h3 q', 'f4 b4 q', 'a6 f6 q', 'h2 b2 q', 'g2 g7 q', 'e1 g2 q', 'g5 g8 q', 'd4 h8 q', 'g7 b7 q', 'a5 e1 q', 'b6 b1 q', 'b7 h7 q', 'h8 g6 q', 'b8 f4 q', 'a4 e8 q', 'h7 a7 q', 'h6 g8 q', 'g2 h4 q', 'f1 h2 q', 'a7 c8 q', 'g4 g1 q', 'a7 a1 q', 'h5 h1 q', 'a4 g4 q', 'c5 g1 q', 'b2 h2 q', 'a2 a8 q', 'h2 a2 q', 'f4 a4 q', 'd8 b7 q', 'b7 d8 q', 'h2 h6 q', 'f5 b5 q', 'a2 f7 q', 'd5 g8 q', 'f6 a6 q', 'h3 c3 q', 'a6 a1 q', 'a2 c1 q', 'f5 a5 q', 'd4 g1 q', 'a3 a8 q', 'd1 b2 q', 'b4 g4 q', 'g4 g8 q', 'g8 e6 q', 'h8 d4 q', 'h2 h7 q', 'g2 a2 q', 'a3 g3 q', 'g7 a7 q', 'h3 h8 q', 'c6 h6 q', 'e8 a4 q', 'b2 d1 q', 'd5 h1 q', 'g5 g1 q', 'g3 b3 q','e1 a5 q', 'b1 g6 q', 'a7 f2 q', 'a1 b3 q', 'g1 e3 q', 'b5 g5 q', 'h3 g1 q', 'g3 b8 q', 'a4 h4 q', 'h7 h2 q', 'h1 f2 q', 'a6 g6 q', 'g6 b1 q', 'b7 h1 q', 'h6 c6 q', 'g3 g8 q', 'g4 b4 q', 'b3 h3 q', 'g7 e8 q', 'g8 d5 q', 'h6 h1 q', 'g1 d4 q', 'h1 d5 q', 'f2 a7 q', 'c8 a7 q', 'g6 b6 q', 'g5 b5 q', 'g4 a4 q', 'h5 b5 q', 'a1 g7 q', 'g5 a5 q', 'b4 h4 q', 'h4 b4 q', 'a8 g2 q', 'c3 h8 q', 'b2 h8 q', 'a3 h3 q', 'c6 h1 q', 'h5 a5 q', 'g6 g1 q', 'b5 h5 q', 'b6 h6 q', 'b8 g3 q', 'h1 g3 q', 'c1 a2 q', 'h3 b3 q', 'f7 a2 q', 'a6 h6 q', 'h4 a4 q', 'g3 a3 q', 'g2 e1 q', 'h7 h1 q', 'g2 g8 q', 'h2 h8 q', 'g7 g1 q', 'h3 a3 q', 'g6 a6 q', 'h8 c3 q', 'h6 b6 q', 'b3 g8 q', 'h7 c2 q', 'h6 a6 q', 'h2 c7 q', 'h1 c6 q', 'b6 g1 q', 'g1 c5 q', 'g8 c4 q', 'h8 b2 q', 'h1 b7 q', 'b1 h7 q', 'g8 b3 q', 'g1 b6 q', 'b8 h2 q', 'a1 h8 q', 'a8 h1 q', 'h8 a1 q', 'a2 g8 q', 'g1 a7 q', 'h2 b8 q', 'h7 b1 q','a7 g1 q', 'g8 a2 q', 'h1 a8 q']

def move_stream():
    while True:
        for move in all_moves:
            yield move

for m in move_stream():
    print(m)

Sopel

Posted 2019-10-29T10:44:49.450

Reputation: 291

This isn't a code golf, but you might be interested in looking up itertools.cycle; for m in cycle(all_moves): print(m) – ymbirtt – 2019-11-01T13:12:08.523

This fails controller.py check, printing an invalid move d8d7 q. – feersum – 2019-11-01T15:28:17.703

@feersum should be fixed... turns out manually removing new lines is error prone... – Sopel – 2019-11-01T15:43:26.477

Sorting from best move to worst move doesn't actually make the best moves be used more. To make a move rarely-used, you need to put it right after a move that's likely to make it impossible (such as another move with the same starting square). – Brilliand – 2019-11-01T18:01:47.853

@Brilliand "Sorting from best move to worst move doesn't actually make the best moves be used more." I'm well aware of that. The fact that we don't reset the move stream after a move has IMO an even bigger impact on the quality and makes it a little bit random, though this issue cannot be solved with the given rules." To make a move rarely-used, you need to put it right after a move that's likely to make it impossible (such as another move with the same starting square)." That's an interesting possible solution. That said, I don't mind people using my statistical results for their submissions. – Sopel – 2019-11-01T18:14:34.377

8

Backline

Backline attempts to take advantage of the fact that its opponent can't see what's going on. It sends one piece at a time into its opponent's back rank, capturing as many pieces as possible before returning each piece to where it started so that it remembers where it is for next time. Backline is written in Python 3.7.

#! /usr/bin/python3

import random
import sys

_, colour, seed = sys.argv[:3]
random.seed(seed)

files = "abcdefgh"

def colour_move(start, end, flip):
    if colour == "w":
        return (7 - start[0] if flip else start[0], start[1]), (7 - end[0] if flip else end[0], end[1])
    else:
        return (7 - start[0] if flip else start[0], 7 - start[1]), (7 - end[0] if flip else end[0], 7 - end[1])

def stringify_move(start, end):
    return f"{files[start[0]]}{start[1] + 1} {files[end[0]]}{end[1] + 1} q"

# This guarantees that if the piece is not taken, it reaches the final square as quickly as possible.
def safely_make_long_move(start, end):
    file_change = end[0] - start[0]
    rank_change = end[1] - start[1]
    used_squares = [start]
    while used_squares[-1][0] != end[0] or used_squares[-1][1] != end[1]:
        used_squares.append((used_squares[-1][0] + (1 if file_change > 0 else (-1 if file_change < 0 else 0)), used_squares[-1][1] + (1 if rank_change > 0 else (-1 if rank_change < 0 else 0))))
    for i in range(len(used_squares) - 1):
        for j in reversed(range(i + 1, len(used_squares))):
            yield (used_squares[i]), (used_squares[j])
    yield None

def rook_attack(p):
    flip = p == "h"
    # Move pawn forward two spaces.
    yield stringify_move(*colour_move((0, 1), (0, 3), flip))
    track = [(0,0), (0,2), (1,2), (1,7), (0,7), (7,7), (7,6), (1,6), (1,2), (0,2), (0,0)]
    for i in range(len(track) - 1):
        move_gen = safely_make_long_move(track[i], track[i+1])
        while True:
            move = next(move_gen)
            if move:
                yield stringify_move(*colour_move(*move, flip))
            else:
                break
    yield None

def bishop_attack(p):
    flip = p == "f"
    # Move pawn forward two spaces.
    yield stringify_move(*colour_move((3, 1), (3, 2), flip))
    track = [(2,0), (3,1), (2,2), (7,7), (6,6), (5,7), (4,6), (3,7), (2,6), (1,7), (0,6), (2,4), (1,3), (3,1), (2,0)]
    for i in range(len(track) - 1):
        move_gen = safely_make_long_move(track[i], track[i+1])
        while True:
            move = next(move_gen)
            if move:
                yield stringify_move(*colour_move(*move, flip))
            else:
                break
    yield None

def queen_attack(p):
    flip = False
    # Move pawn forward two spaces.
    yield stringify_move(*colour_move((4, 1), (4, 2), flip))
    track = [(3,0), (7,4), (7,7), (0,7), (0,5), (7,5), (7,4), (4,1)]
    for i in range(len(track) - 1):
        move_gen = safely_make_long_move(track[i], track[i+1])
        while True:
            move = next(move_gen)
            if move:
                yield stringify_move(*colour_move(*move, flip))
            else:
                break
    yield None

def knight_attack(p):
    flip = p == "g"
    # Move pawn forward two spaces.
    track = [(1,0), (2,2), (1,4), (2,6), (0,7), (1,5), (3,6), (5,7), (6,5), (7,7), (5,6), (3,7), (1,6), (2,4), (0,3), (2,2), (1,0)]
    for i in range(len(track) - 1):
        yield stringify_move(*colour_move(track[i], track[i+1], flip))
    yield None

# Just Everything's code:
colnames = "abcdefgh"
rownames = "12345678" if colour == "w" else "87654321"

def coord2code(col, row):
    return colnames[int(col)] + rownames[int(row)]

def buildmoves(col, row):
    # Knight moves
    for x in (1, 2, -2, -1):
        if x+col >= 0 and x+col <= 7:
            for y in (2/x, -2/x):
                if y+row >= 0 and y+row <= 7:
                    yield (x+col, y+row)
    # Bishop moves
    for x in range(1,8):
        if col+x <= 7:
            if row+x <= 7:
                yield (col+x, row+x)
            if row-x >= 0:
                yield (col+x, row-x)
        if col-x >= 0:
            if row+x <= 7:
                yield (col-x, row+x)
            if row-x >= 0:
                yield (col-x, row-x)
    # Rook moves
    for x in range(1,8):
        if col+x <= 7:
            yield (col+x, row)
        if col-x >= 0:
            yield (col-x, row)
        if row+x <= 7:
            yield (col, row+x)
        if row-x >= 0:
            yield (col, row-x)

def allmoves():
    for row in range(8):
        for col in range(8):
            for to in buildmoves(row, col):
                yield ((row, col), to)

movelist = [(coord2code(*a), coord2code(*b)) for (a,b) in allmoves()]
random.shuffle(movelist)

# Avoid Scholar
print("g2 g3")
print("g7 g6")

# Choose random piece to attempt to kill the enemy with.
used_piece = ["a", "b", "c", "d", "f", "g", "h"]
random.shuffle(used_piece)
while True:
    # Try to kill off their pieces by sending one piece at a time in to attack
    for p in used_piece:
        if p in ["a", "h"]:
            move_gen = rook_attack(p)
        elif p in ["b", "g"]:
            move_gen = knight_attack(p)
        elif p in ["c", "f"]:
            move_gen = bishop_attack(p)
        elif p == "d":
            move_gen = queen_attack(p)
        while True:
            move = next(move_gen)
            if move:
                print(move)
            else:
                break
    # Break out of possible checks by trying every possible move once.

    for (a, b) in movelist:
        print(a, b, "q")

Apologies for the somewhat messy code. Backline does reasonably well; against the current field it placed first in my tests, with 107 of 160 possible points.

Spitemaster

Posted 2019-10-29T10:44:49.450

Reputation: 695

2Shouldn't the hashbang be #! /usr/bin/python3? Aliasing /usr/bin/python to Python 3 can seriously bork a system. – Peter Taylor – 2019-10-31T23:31:01.517

This seems to fail some of its attacks (generally, the ones on the kingside) due to the attack functions not flipping horizontally. – Brilliand – 2019-11-01T01:43:25.337

@Brilliand colour_move should flip them, and in my tests it did. Is it failing somehow? – Spitemaster – 2019-11-01T03:13:12.127

@Spitemaster It flips vertically, but I'm talking about horizontally. – Brilliand – 2019-11-01T03:20:52.330

@Brilliand It should do both - 7 - start[0] if flip else start[0] should flip it horizontally, and flip is True when p is f, g, or h. – Spitemaster – 2019-11-01T03:29:53.887

@Spitemaster Oh that's true... I know I saw the h-file rook fail its attack, but it looks like that was for an unrelated reason (the g-file pawn blocked it). – Brilliand – 2019-11-01T04:01:57.790

1Something like this was the first thing I thought of when seeing this challenge. Nice work. – BradC – 2019-11-01T13:45:03.793

1@PeterTaylor The hashbang is totally non-functional anyway due to the space after the bang... – feersum – 2019-11-01T15:02:25.353

@feersum tbh, I just copied it from JustEverything. :P – Spitemaster – 2019-11-01T15:33:15.470

8

Prickly

Focuses on defensive captures, by sending a large number of probably-illegal moves after each move in its opening plan. The opening plan focuses on moving pieces to locations where they can easily defend each other.

It tries to transition into a Zombie March midgame with an endgame based on a group of queens sweeping the board, but usually that fails and it winds up in its Just Everything fallback mode.

#! /usr/bin/python

import sys
import random

_, color, seed = sys.argv[:3]

random.seed(seed)

colnames = "abcdefgh"
rownames = "12345678" if color == "w" else "87654321"

def coord2code((col, row)):
    return colnames[col] + rownames[row];

def sendmove((a, b)):
    print coord2code(a), coord2code(b)

def long_safe_move(start, step, length):
    a,b = start
    x,y = step
    i = 0
    while i < length:
        m_start = (a+x*i,b+y*i)
        j = length
        while j > i:
            m_end = (a+x*j,b+y*j)
            if m_end[0] >= 0 and m_end[0] <= 7 and m_end[1] >= 0 and m_end[1] <= 7:
                yield (m_start, m_end)
            j -= 1
        i += 1

captures = ([((x,1),(x+1,2)) for x in range(7)]
         + [((x+1,1),(x,2)) for x in range(7)]
         + [((0,0),(0,1)), ((1,0),(3,1)), ((2,0),(1,1)), ((2,0),(3,1))]
         + [((7,0),(7,1)), ((6,0),(4,1)), ((5,0),(6,1)), ((5,0),(4,1))]
         + [((3,0),(2,1)), ((3,0),(3,1)), ((3,0),(4,1)), ((4,0),(5,1))])
captures.remove(((3,1),(4,2)))
captures.remove(((4,1),(3,2)))
sendmove(((6,1),(6,2)))
captures = [m for m in captures if not (6,1) in m]
for m in captures:
    sendmove(m)
sendmove(((6,0),(5,2)))
captures = ([m for m in captures if not (6,0) in m and m[0] != (5,2)]
         + [((5,2),(7,1)), ((5,2),(3,1))]
         + [((x,2),(x+1,3)) for x in range(7)]
         + [((x+1,2),(x,3)) for x in range(7)])
for m in captures:
    sendmove(m)
sendmove(((5,0),(6,1)))
captures = ([m for m in captures if not (5,0) in m]
         + [((6,1),(5,2))])
for m in captures:
    sendmove(m)
sendmove(((4,0),(6,0)))
captures = ([m for m in captures if not (4,0) in m]
         + [((5,0),(5,1)), ((6,0),(5,1)), ((6,0),(6,1)), ((6,0),(7,1)), ((6,0),(5,0))]
         + [((x,3),(x+1,4)) for x in range(7)]
         + [((x+1,3),(x,4)) for x in range(7)])
for m in captures:
    sendmove(m)
sendmove(((1,1),(1,2)))
captures = [m for m in captures if not (1,1) in m]
for m in captures:
    sendmove(m)
sendmove(((1,0),(2,2)))
captures = ([m for m in captures if not (1,0) in m and m[0] != (2,2)]
         + [((2,2),(0,1)), ((2,2),(4,1))]
         + [((x,4),(x+1,5)) for x in range(7)]
         + [((x+1,4),(x,5)) for x in range(7)])
for m in captures:
    sendmove(m)
sendmove(((2,0),(1,1)))
captures = ([m for m in captures if not (2,0) in m]
         + [((1,1),(2,2))]
         + [((x,5),(x+1,6)) for x in range(7)]
         + [((x+1,5),(x,6)) for x in range(7)])
for m in captures:
    sendmove(m)
for m in captures:
    sendmove(m)
sendmove(((3,1),(3,3)))
sendmove(((3,2),(3,3)))
captures = ([m for m in captures if not (3,1) in m and not (3,2) in m]
         + [((5,2),(3,3))]
         + [((x,6),(x+1,7)) for x in range(7)]
         + [((x+1,6),(x,7)) for x in range(7)])
for m in captures:
    sendmove(m)
for m in captures:
    sendmove(m)
sendmove(((4,1),(4,3)))
sendmove(((4,2),(4,3)))
captures = ([m for m in captures if not (4,1) in m and not (4,2) in m]
         + [((2,2),(4,3))])
for m in captures:
    sendmove(m)
for i in range(8):
    sendmove(((i,6),(i,7)))
for m in captures:
    sendmove(m)
sendmove(((3,3),(3,4)))
captures = ([m for m in captures if not (3,3) in m]
         + [((2,2),(3,4))])
for m in captures:
    sendmove(m)
sendmove(((4,3),(4,4)))
captures = ([m for m in captures if not (3,3) in m]
         + [((5,2),(4,4)), ((5,2),(3,3)), ((2,2),(4,3))])
for m in captures:
    sendmove(m)
captures = [m for m in captures if not (2,2) in m and not (5,2) in m and not (1,1) in m and not (6,1) in m]
for m in long_safe_move((0,7), (1,0), 7):
    sendmove(m)
for m in captures:
    sendmove(m)
for m in long_safe_move((7,7), (-1,0), 7):
    sendmove(m)
for m in captures:
    sendmove(m)
for m in long_safe_move((1,1), (1,1), 6):
    sendmove(m)
captures = [m for m in captures if not (1,1) in m]
for m in captures:
    sendmove(m)
sendmove(((6,1),(6,0)))
sendmove(((7,1),(6,0)))
for m in long_safe_move((6,1), (-1,1), 6):
    sendmove(m)
captures = [m for m in captures if not (6,1) in m]
for m in captures:
    sendmove(m)
sendmove(((2,1),(2,3)))
sendmove(((2,2),(2,3)))
captures = [m for m in captures if not (2,1) in m and not (2,2) in m]
for m in captures:
    sendmove(m)

def buildmoves((col, row)):
    # Knight moves
    for x in (1, 2, -2, -1):
        if x+col >= 0 and x+col <= 7:
            for y in (2/x, -2/x):
                if y+row >= 0 and y+row <= 7:
                    yield (x+col, y+row)
    # Bishop moves
    for x in range(1,8):
        if col+x <= 7:
            if row+x <= 7:
                yield (col+x, row+x)
            if row-x >= 0:
                yield (col+x, row-x)
        if col-x >= 0:
            if row+x <= 7:
                yield (col-x, row+x)
            if row-x >= 0:
                yield (col-x, row-x)
    # Rook moves
    for x in range(1,8):
        if col+x <= 7:
            yield (col+x, row)
        if col-x >= 0:
            yield (col-x, row)
        if row+x <= 7:
            yield (col, row+x)
        if row-x >= 0:
            yield (col, row-x)

def allmoves():
    for row in range(8):
        for col in range(8):
            for to in buildmoves((row, col)):
                yield ((row, col), to)

movelist = [(a,b) for (a,b) in allmoves()]
random.shuffle(movelist)

for (a, b) in movelist:
    if a[1] != 7:
        sendmove((a, b))

for i in range(8):
    sendmove(((i,7),(i,6)))
for i in range(7):
    sendmove(((i,7),(7,i)))
for i in range(1,8):
    sendmove(((i,7),(0,7-i)))
for m in captures:
    sendmove(m)
for m in long_safe_move((0,6), (1,0), 6):
    sendmove(m)
for m in captures:
    sendmove(m)
sendmove(((6,6),(6,7)))
sendmove(((5,6),(5,5)))
sendmove(((4,6),(4,4)))
for m in captures:
    sendmove(m)
for (a, b) in movelist:
    if a[1] < 4 and b[1] < 4:
        sendmove((a, b))
for i in range(3):
    for m in long_safe_move((7-2*i,6), (-1,0), 2):
        sendmove(m)
    for m in long_safe_move((6-2*i,7), (-1,0), 2):
        sendmove(m)
    for m in long_safe_move((5-2*i,5), (-1,0), 2):
        sendmove(m)
    for m in long_safe_move((4-2*i,4), (-1,0), 2):
        sendmove(m)
    for m in captures:
        sendmove(m)

while True:
    for m in movelist:
        sendmove(m)

Brilliand

Posted 2019-10-29T10:44:49.450

Reputation: 1 166

6

BlindMoveMaker1

BlindMoveMaker1 follows a genetic approach. During a game BlindMoveMaker1 uses a constant move list with fixed order which was evolved by a genetic algorithm (GA) off line. BlindMoveMaker1 simply cycles through the move list repeatedly. A move list starts with an opening part of 200 moves, followed by a main part of 1792 moves.

The opening part is a list of genetically picked moves (from the set of all possible moves) and move order. The main part is guaranteed to contain every possible move (not to lose because of a forfeit) but in a genetically tuned order.

Each move list was developed for white. When playing black each move is re-coded for black (e.g. turns 'e2 e4' into 'e7 e5').

The move lists were evolved off line by my GA playing against my beloved enemies (so far): Pokey, Prickly and Backline as sparring partners.

My GA is designed in such a way that the opening part is in the center of the genetic mutating (and crossover) storm while trying to evolve better move lists.

This GA is still running on my laptop. This way I hope to find even better move lists until the deadline.

Until now, it self-learned how to resist Pokey's/Prickly's early checkmate attempts.

import java.util.Random;
// Version 2.0
public class BlindMoveMaker1 {
    public static void main(String[] argv) {
        String list[] = {
                /* fitness      conf id           gen */
                /* 0.4862317      31 94e0a298    "d6c8 a4b3 e5b2 c1e1 h5h8 g6a6 c2c3 d6h2 c1h1 g2g5 c1f1 b1b8 d1d6 f3e5 d3d8 e6e2 g4g7 d6c7 d1b2 h6h4 c6c8 f7f3 c5b5 e1f3 b1a1 d6b8 e6f7 f3h1 h8e5 e1h1 b7a6 f6g5 a4b5 f2a2 f1e1 c2c1 d2f2 f7g7 a2a8 b6g6 h7h2 f2f3 b6d6 d5d1 c1c6 g2d2 f7g8 c1c2 e1c2 h6e6 d4d6 b4a2 g8d8 c4g8 e8h8 h3f2 c3h3 c5c6 c5f5 d4d1 d7c8 h2f4 c1a3 f3a8 b1e1 e7g6 h6d6 d4d2 d7b6 a2b2 h7g5 c6h1 b7f3 a8g2 f4a4 c1c5 d5b6 h5e8 f1h2 f6f3 a6b8 c4g8 e7e1 b7d7 f3h3 b7b3 b2b5 c6g2 g4g7 a3a4 g5d2 a3f3 b5a3 f1c4 h2f3 h2g4 g5h5 h7h3 b1d3 d4a1 a8d8 a5d2 d5h1 c7c4 f2e2 g7c7 e8e4 a4a7 c4c1 d1d7 h7h2 c2a1 e4c5 h1c1 h3h2 b1d3 f6h5 a3a4 h7h1 h1h3 f2f7 g5e3 e2c1 h1h5 g3d3 h4h1 c6e4 c6b8 a7a3 g4h3 c5d3 c8d8 f1f7 d3e5 b2d1 g7f5 c7c8 a4h4 a5c3 c2c6 a7e7 g3c3 e4c6 b3f3 f4d2 a8c7 h2a2 g3e2 f6h7 b8a7 d2d5 d7d1 g6b1 e2d4 d8b8 d4f6 h1g1 c2d4 g8b3 f7c4 c2a3 h1g1 c3a3 b5b2 e4f4 d1d3 b5d3 f8c5 a6f1 e2a6 a1d1 c8b8 c4c1 c5f5 a7a6 g6a6 e3d3 b1c3 b6a7 c1c2 f5e7 h8g8 e4c2 a4c6 a5d5 c5c2 f4e2 c7e5 e8d6 d6c8 e3f5 c3e2 f3a8 c8g8 c1c6 a4e8 g7e5 c6h1 f4g5 e1e2 f1h3 a4a5 a5a6 f4g5 g6h5 h4h5 g4g3 a6a7 g3g4 g6g7 h6h7 h2f4 h2h3 c5b6 b8a8 g7g8 a7a8 e2g4 e1d1 h6h3 h3h4 a2a3 h5g5 a2e6 g5f5 g8f7 b2b3 e6f4 c3b4 e1e2 c5c6 c4c5 c3c4 g4g5 f1e2 b7b8 b6b7 b1b8 g4g2 d4c5 d2e3 g8h8 a1a2 d1d2 d4d5 d1e1 h7g5 f7f8 b4b5 d7d8 h5g6 b4a5 b4c5 e2d2 d2e2 g4h5 a2e2 c1d1 b5b6 g8f8 b1c3 f5f6 g7f8 f1e1 f5h6 h8g7 a5c4 c3b3 c6c7 e4f5 g6h7 e1d2 e7e8 e6e7 c7c8 f2g2 e2f2 f4f5 h2h1 e7d8 e5e6 d6e7 h7g8 f8e7 g2f3 c1b2 g8h7 f3a3 d2c1 f6f7 e6d7 f8g8 d7b6 c5b4 c1d2 h8g8 f7g8 e2e3 f8e8 d8c8 a1b1 b2h8 c3d4 d5c6 d2d3 e2d1 e2f3 f2f3 b2c3 e3e4 e7f8 f3g4 b7c8 c7b8 a1a5 c2c3 c4b5 a1a3 g7h8 d8e8 f4e5 d3c3 e8c8 h8h7 c8b8 d5d6 b7a8 d2d1 e2d3 f5f1 g6f7 a7f2 f4d2 c6d7 g1g2 d1c2 e1f1 d7e8 h2h4 b2d3 d6d7 d3e3 g3f4 e5d6 g7g1 g3h4 h3h1 a7b8 e8f8 d1e2 c4d5 c6b7 c8d8 h6h5 e3d2 b1a1 b8a7 h4g5 a8b7 c5d6 c7d8 e8e7 d3c4 f5f4 c2c4 h6g7 g2f1 g1f3 d5b7 h1h3 a7c5 f3e4 f4d6 h3h2 h8e8 g7f7 a2b2 b6c5 g2h2 f1g2 c4c3 d3d2 a1b2 d7c8 f6g7 e7d6 d8d7 c1e3 b6c6 a2a4 f6e5 a6b6 a2b3 f3e2 d3e2 b6a7 a2c3 c4e4 b3b2 g3h1 c5h5 b2a3 g2h3 b8c8 a5c3 d3d4 d6c7 g2f2 b7d7 b1c1 h8a8 b4c3 f1f2 c1b1 d3e4 d7e6 f7g7 b4c4 d2d4 d5e4 d7c7 b3c3 b7d8 e5f6 d4e4 g4f5 g3h3 f1g1 a3b3 e6f7 b7g2 h3g3 e4c5 h3g4 c3d2 a4b5 b2a2 e5d5 g1f1 g5g6 h4g3 f7g6 d6b6 b5c6 h3h5 h1g2 h7g6 f2f4 g6f5 g7g6 c7d6 f4f3 d3h3 g2g3 a4a3 c4f1 f2g3 b2a1 a5b6 e7f7 d6e6 a7b6 f5g4 f3e3 c6d5 c7d7 e5f4 f7f6 e7d7 e8d7 h2g1 c2d3 b4b8 h5h4 e3e2 g4f3 d5e5 f4e4 a3b4 a3a2 d7e7 b5a4 a5b5 b3c2 a8a6 c2b2 g6h6 g7f6 f2f1 c4d4 f2e2 f7e7 c4d3 b5c5 f7b3 g8g7 f6e7 b8c7 c5a6 c8c7 c2f2 e3g2 g2h1 d2c2 a3b2 a4a8 d5d4 c6d6 d4d3 f2e3 a1a4 d4g4 c3d5 b7c6 g6c6 h5h6 b6c7 a7b7 g1h2 h2g3 d7d6 e4d3 h4h3 a1d1 c3d3 g1h3 f7e6 g2g1 f6g6 e3f2 e3f3 b5c4 b6a5 a6a1 e6f6 g1e2 f3f2 e6f5 c2c1 c3c2 d5h5 h6g5 a8h8 f5e4 h4g4 c2b1 b6b5 f4g3 e6a2 g5f4 e6e5 d5c4 e6g6 b1d2 d4c3 a4b4 b1b2 a1e5 b7a7 b3a2 e2e1 d3c2 c3h8 f3g3 e1f2 b2b1 a8b8 h2g2 c3e4 a5a4 f4g4 c6b5 c7b7 b4a3 e7e6 b7b6 e1e5 f3d5 d5c5 e4g3 g6f6 b1a2 e4e3 b2c2 h7g7 d6d5 d6e5 g4h3 b7c7 b3a4 f1d3 a8c6 b1d1 g1h1 f3g2 g3f3 c3b5 h3g2 c5c4 d7c6 b4d2 e3d4 c3c5 f4e3 b1a3 h6h2 b4a4 d3f5 b8b7 g7h6 g1f2 e4f4 g3g2 d2f4 g3h2 d8e7 f8h6 c3b2 f6g5 d1d3 a3a1 c1d3 c4b4 c5b5 f2g1 c2d2 d8c7 e5e4 h7b7 g4f4 g7h7 g5h5 a2b1 d5e7 g1g3 g5h4 h6f8 c2d1 b5b4 b6a6 c4b3 h5g4 e8c6 f1c4 c5d5 a1c1 c8e8 h3g5 f5g5 e4e2 g4h4 f5e5 f6d8 g6h8 b5c7 b3b8 h3f3 c5c1 c5e7 d2d8 e2d4 a8c8 h1f1 e8e6 b3c1 a4b3 c7c6 a7a3 a5c7 h7f5 d5g2 d4f4 g3f2 e7c8 b7b3 g7g5 g5f7 b7a6 b1c2 g6g4 f3g1 f3d4 b1f5 a7g7 h2f2 c7b6 a6a5 f6f5 e6d5 f7d8 e4f3 b8b4 f7g5 d2b2 g8e8 h5h7 f6e6 f6h8 c3b1 e8h8 h8e5 g7c7 g4e3 d8a8 a8a1 a5d8 a8d5 c6b6 c8a8 c1a3 d2b4 a3c1 d6f4 g2g4 d2e4 e1h1 e2c2 h4f4 f8a3 h8d4 e8g7 h6f4 g7g3 c8d7 h6g6 h2e2 f1f3 d8g8 d5b6 c8b6 e4c6 d8b6 a3a8 f8d6 f1h1 a1h1 g1e1 h3g1 f8f6 a6f6 f4d4 e3e1 d5e6 g6e7 c1e1 e7f5 d8b7 g4e2 a8h1 f8h8 d4e6 h7f6 f5h7 h7f7 f3d1 a1e1 c2e4 c8h3 c5c2 b8e8 d5c7 e6d8 d8f8 h1e1 f4h2 g5h7 e7e1 a4g4 a8e8 e1g1 c4e2 f3h2 f4g2 a8c7 d7e5 h1h2 e5f3 f6e8 d5f7 e7e4 d1h5 e1a1 b6d7 f3g5 d4h8 e4d5 a3a5 e4d6 a6h6 a3f8 a3c3 b8d8 e4a8 h2h6 e4f6 h3f1 e8g6 f3e5 g8e6 d8a5 a2d2 h7f8 h3f5 e5f7 b7f3 e5d7 e8a8 f3f7 h1a8 g8a2 b6a8 d4f6 a7d4 f7e8 c7a8 f8c8 h8h6 h5h8 f3f1 f2f5 c1f4 b8d6 d5f5 e4g6 h5f3 a1f1 h2g4 a3b5 a3c2 g6e6 c6f6 h5e2 a8g8 a2c2 e1b1 f8h7 f4h4 c8h8 d5a8 f8b8 g6e8 a8g2 e6e8 a8b6 e5c7 e8f6 c6e8 d4c6 d1b3 e7g7 e4c4 g7d4 e4f2 d7h3 d7f5 c1h6 a7e7 f2e4 b5d7 c1c2 f3f5 h8f8 c6e6 d7f7 b2b4 f8c5 e6c4 e2f4 d7f8 d3f2 b7c5 e5g7 a1d4 b3c4 d2f2 e3c3 f8g6 a3b1 b3a3 a7a6 h1c1 d3d6 d2f1 g1a7 g7e7 b8h8 e3b3 c2c5 b1f1 d6f5 a4a6 f1c1 h2b8 b4d6 c1c3 d8f6 a1c3 f7b7 f4f6 b3b7 h8g6 c2g2 d4e2 f7e5 a8f3 c3e5 e8b8 d2a2 h8c8 d2g5 e6g8 g5d2 c2a2 a8a4 c8c6 d8e6 g2e4 a8f8 a1h8 d4f2 e7c7 f8f4 c1c6 e7g5 c6c8 c5f8 f8g7 a7d7 g6g5 a8a3 f7d5 g7f5 h5f7 e4d2 h3f4 b8d7 f2d3 b1h1 h8b2 f1d1 g2a8 f5d4 f4g6 e7e5 a7c6 h1d1 a1g1 g8b8 d2f3 d5e3 b5e5 f3c3 a2h2 f5h4 e8e1 a3h3 f2h2 g5e3 d3b3 h1h6 c8c2 h8h1 d6g3 d8d5 c4d2 h6f7 d1f1 f8f7 f6e4 a5a7 b4d4 e7c6 h8d8 f5f3 c8e6 c8c4 f8d8 h3c8 c3f6 h5f5 a6a4 h4f3 f6f2 b3b4 d1h1 f1b1 e5e2 b8b5 f5g6 b6d4 d3b5 g8d5 d6a3 f5d3 g4e6 d2h2 d8d4 h7h8 h5e8 f3d2 a7f7 h7e4 a4c3 d6e4 e1c1 h8h3 d2a5 d8g5 d2c4 g6d3 f8b4 c4a2 b3e3 g6g3 c4d6 g3d6 g5e6 h3a3 h8h4 e8g8 g3f5 a6e2 c5a4 c4f4 f3a8 e2b2 e4c3 g8h6 d8h4 c5d7 e6c8 d5f4 e5e3 h1h7 d1g1 c6b4 f6d5 d4b3 d6b8 d3f3 c6a6 f5e3 e5a1 c5e3 h3f2 d3d1 d8h8 g6e4 c6d8 c8f5 a6b5 e7g8 b1b4 b5b7 e3f5 b7b4 g7d7 e4c2 f3h4 g8g1 c7a7 f6c3 a5c5 c2b4 g8d8 c3f3 c1g1 b5d6 e8d6 h1h5 c3e3 d7d5 d5f6 c1g5 f2d2 b1g6 f4c7 a3c4 a2a8 d6h6 f5h3 h4h2 d3d7 e8f7 d5f3 a6d3 e7c5 f4e6 c7e6 b2e2 h3d3 h8a1 e8a4 d4f3 a4a2 e1e6 d2e1 b6b8 a5b4 d6e8 c4c1 h7h6 e2c3 b3d3 g8b3 b3d5 c8e7 c2a4 d5d1 a4c4 d1d4 c4c2 d8d1 c8f8 d1g4 e2h2 a6c6 f5c5 d8d2 d4g7 g4h6 g5f6 f3h3 d6h2 e2b5 h6h8 a8a5 e2g2 a5a2 g4g7 e7a7 c7d5 e5d3 d3g6 f7c7 b2d2 b5b8 c7a5 c7e7 e5h2 d7f6 c3e2 d8b8 a1a6 a1a8 h1a1 d5b3 d1d5 h7b1 f4f2 f7d7 h4f6 e3g4 a2b4 d2b1 d4b2 c8g8 c6d4 c4c6 d7b7 f5f8 f6h7 d4a1 f1a1 b5b1 g2e2 g1d1 f1f5 g8g5 c6a8 e6e4 h8h5 g7e8 h8b8 e2e5 c3a4 c8c1 f4f1 d4e3 e4g4 g3d3 e6c5 d4c2 e2h5 b8g8 g3g1 h6c6 g4g6 a5d2 a4c6 b2g7 a1c2 g2c6 h5d1 e3d5 g3g8 b4a6 h1h8 e6g4 d3e5 d1b1 b1b3 e5b8 c3a5 e7h7 g5g3 d4b4 f7f5 h6c1 f3d3 f6h4 e3d3 g1g4 d3g3 h8f7 h1h4 c2d4 e5c4 f6h6 b7e4 c1c8 f5c2 d6d2 e3g3 d8c6 d1a4 c2e3 c3a1 c5a3 f5g7 b4b6 b5d3 b3b5 b7e7 e3h6 d6c8 a6b4 e4e1 d5d7 c4a6 f7d6 c7e8 g5d5 g8f6 g8e7 f5g3 d4d8 f1f4 e5c5 h8f6 g2d2 e5b2 d1e3 a5a1 a3d3 a4c5 a1g7 d1f2 f6d4 f4e2 e3c2 b1e1 h2d2 d8d3 h7d7 e4h4 b3a1 b3g8 e5e7 d5h1 e5c6 h1b1 a4b6 a6c4 b2f6 h1d5 d1d8 h6e6 c8a6 e5g3 c4c8 a5a8 a2a5 c6a4 e5g4 c6c4 c6h6 d7d2 e3f4 c7c5 e5h8 g5d8 e4a4 d5b5 a3e7 d6d8 e7b7 g3e5 d4d1 d7d4 c3c6 e5d4 e2g3 e3c5 c7e5 c5c3 g5e4 f4b4 b7h7 g3e1 d5d2 a4h4 c1a2 d7b5 b6f2 c6e4 g4f6 e5e1 b4e7 h2h7 a7g1 d4h4 d3b1 g2g8 d5d8 e3f1 e1e4 g5h6 b6a4 e2c1 b6b3 d1f3 e4e7 g1b1 h3e3 e6c6 b1b6 b8e5 e3c1 d5d3 b5e8 e5c3 e1e7 h5d5 c3g7 b4c2 g2g5 h7a7 c5c7 a4c2 f7h7 c7f4 c5b3 b2f2 a2a7 h7c7 c2e2 f7c4 b1d3 b8f4 f4c1 c7g7 c5a7 g8a8 b1h7 c3d1 a7a5 b2e5 e5e8 f3h1 b4g4 g2e1 d7g4 d4g1 h1e4 h1g1 a4e4 e1g3 e6b6 h2c2 c2c7 d6f6 e6d4 f5c8 c2e1 c2b3 a3d6 a4a1 b4f4 b6b4 h5e5 b4b7 a7e3 d6a6 b3b1 c4a4 f2a7 c6e7 a5e5 f7h6 e7b4 e7d5 h6d2 b2b5 b5d5 e8b5 b3c5 f2g4 h1b7 f1b5 c7h7 d2c3 h1f3 c2a3 g7b2 c5e4 c3a2 d1d7 a6a2 a2c4 b4b2 e1e8 b5a3 b4f8 b6b2 e7g6 a4f4 b7b1 f3b3 h3e6 g7e5 h2b2 d2b3 e7h4 h2f3 c7a6 d4b5 g1g8 g7h5 c2g6 g8g6 g8c4 f6f8 f5b1 f5d7 e2c4 f1a6 e8e4 c5f2 a2d5 d7b8 h4f5 c5e5 c4b2 e4b4 e6c7 h4h8 c6b8 e3c4 e8h5 g3e4 c3c1 c6e5 b2b6 e3g5 d6f7 f6g8 f8f5 f6f3 h2e5 h4e4 d7a7 f5a5 b8h2 c4e6 f8a8 g2g7 c2a1 a7c7 a2f7 d6d4 h4e1 g2c2 e8e3 f1f6 d1c1 d4d2 a4d4 f2b2 a7h7 g2f4 h3h8 f6f4 e3b6 h7d3 b6d8 f1d2 c4g8 g4f2 f5e7 h4c4 g3g5 d1d6 a2f2 c8g4 f5h5 g1d4 g2b7 e4g5 e6e3 e2e6 d1a1 b5c3 b3h3 e2e8 b1b5 b5a6 g6h4 h7e7 g1a1 f6d6 c6c5 f7a2 b2c1 f2h4 c1f1 h7h1 f2d1 b3e6 g5h3 c4e5 e6f8 d5a5 c3g3 d3a3 c5b7 b5b3 e2a2 d2d7 f4f8 f2f7 g5g4 b2d1 g6b1 h6f6 h6a6 c2c8 b8b3 a5g5 e7e2 c1c4 a5f5 f4h3 e7f6 f5d5 c3h3 c5f5 b3b6 b5a7 d6b7 b4d5 d7g7 g7c3 a6b7 a3g3 a6a3 e2g1 g4c4 e5g6 a8a2 c7c2 a6e6 e3d1 c3e1 a6g6 f7h5 b7g7 e3a3 g5g2 a1b3 a4d1 e3e6 f4d5 e3h3 g8g2 c4e3 f6b2 a5c6 g6f8 b7b5 a4e8 b3d2 e6h6 a1a7 f5e6 f4c4 a3c5 f5f7 g1g7 c6f3 b3g3 e2f1 b6c4 d6c6 a3e3 d4f5 b5f5 h2h8 b7d6 c5c8 e8d8 c8c3 d8d6 e3e5 e6g7 d3f1 b4c6 b3d4 g4h2 a8e4 h5h3 b8b6 f6a1 d5a2 g6d6 e4e5 c2c6 b3a5 a6f1 b5a5 f3b7 g7a7 g7e6 e1b4 h6h4 e6e2 f3f8 g3g7 d3c5 g4d1 d6b4 g3h5 a7a4 f6f1 d4e5 g2a2 b6f6 g3f1 b8f8 c4c7 f8f3 b5d4 c4b6 c1e2 b3f7 e1c3 f4b8 b4d3 f4h6 c5d4 h4d8 h1c6 e2e4 h5h1 d6g6 g4e4 a3a4 g6g1 f6g4 f8e6 f5b5 f2e1 f2h3 d4a7 d4d7 b1g1 e6d6 a6a8 b2g2 e1g2 g5b5 h5h2 h4h6 c4g4 b6e3 f2c5 b8c6 e2a6 e8e5 a4a7 f8d7 c7f7 g6b6 f3f6 a6d6 c6a5 g4e5 g4g8 d8f7 b3d1 f1g3 f4f7 f6c6 f3c6 h7h4 b8g3 b4a2 a6c7 d4b6 b2b8 g4d4 b6e6 a2c1 h6g4 d7c5 e3e8 a5b3 b2d4 e7a3 e1c2 h3d7 g1g5 g5g8 b1e4 b6g1 b1b7 h4f2 b7f7 f7f3 f4h5 e4e8 c6g6 e5g5 c6h1 f2c2 h4d4 g1c1 g3e3 a3a6 b2c4 f5d6 a7b5 h7h3 e1a5 e6b3 h5f4 b4b3 c7c3 c6c2 a7a2 h3b3 d4a4 b8b2 d6d1 f3e1 e4e6 a5d5 c7c4 h7h5 d3b4 c5a5 h8h2 h5b5 g3e2 b6c8 f1f7 h2a2 d2h6 g4c8 g8g4 f2d4 h4h7 d1c3 g2d5 e5f5 h2c7 g7g4 g5g7 a8a7 g1g6 e6g5 c6c3 e1f3 g2e3 e8e2 f7f4 f3h5 e4b1 f7f2 c5e6 e2e7 e5h5 c2f5 d6d3 g5e7 e4b7 e4h1 f4d3 f3f4 b5e2 e4d4 b4b1 a1f6 f2f8 g3b3 c7c1 h4g2 b8a6 c4a5 h1f2 a6c8 f2f6 d3c1 d3d5 d3d8 g4g1 c1b3 g4d7 d3e1 c5g5 a6c5 f2a2 b2h2 h6h1 c3a3 g6g8 d1b2 f8f1 c1a1 a8d8 d6b5 c4f7 d3a6 d4d6 c5d3 b7a5 e6h3 f1f8 g5e5 a5e1 g5c1 g5a5 c2h2 e6a6 h4e7 h2h5 g5c5 f7f1 d3f4 c6a7 c7h2 g3g6 f4a4 e3g1 c6g2 e7e3 d6c4 d7d1 b5b2 b7d5 f6d7 a3f3 h5f6 b2b7 a2g2 b3f3 c1c5 a5b7 b6b1 c8d6 a4d7 e3a7 g6c2 g6e5 d2g2 d2d5 c1c7 g6g2 a5a3 h4h1 b7h1 f1e3 e4g2 h5c5 e1h4 c3c8 b5h5 c7b5 b6d6 f7a7 b4e1 h4a4 h6d6 c4a3 d5c3 b6d5 f6a6 a2a1 h6g8 b7b2 h8c3 f5f2 f2h1 g6f4 c5g1 c3c7 h3h7 h2f1 e8c7 e6e1 g3c3 g1c5 b6g6 g1b6 a2g8 g8c8 h1g3 c7g3 e3e7 b8b1 g3b8 h5a5 d3b2 a4b2 a5h5 h4b4 h7h2 d6c5 b5f1 h6e3 g7g2 a6b8 c8b7 c8c5 g5f3 f6h5 d7h7 d4c4 g1e3 h7c2 f7h8 g4a4 d3h7 c1h1 a3a7 g6a6 h5g3 a7a1 b6h6 b4e4 b2a4 h3c3 g3c7 h2d6 d5g8 g7b7 f8f2 c6c1 d5g5 e4h7 b5g5 d2d6 h4g6 g7a1 f1h2 d5b4 d6f8 e1d3 h6f5 g2g6 e1e3 e5b5 c8a7 e5a5 g8g3 g2b2 a2a6 g3a3 g4b4 f2b6 h6b6 f6b6 d7a4 c4h4 g2h4 g5g1 h3h6 h5g7 b4h4 c2h7 a7c8 d7d3 ",
                /* 1.3935257     147 90915c9b */ "b1d3 d2b3 e2e3 d2b3 d1h5 d1f3 g1h3 h3g5 e2g4 h5f7 f3f7 b1b2 f1f2 d1d7 f2f6 f2f6 b2c1 b1b3 g1f2 d2b4 b2b3 a2b3 f1f6 h1f2 g1f2 b2h8 d2e3 c1b3 f1d3 f1e3 f2d3 e2e3 h1f2 h1f2 c1e3 g2g4 d1f2 a2a3 d1d3 c1e3 a1h8 b1b3 a2c3 c2b3 e1d3 e1d3 d1d3 d1c3 a2b3 f1f6 b2b3 e2g4 h1f2 d1b3 h1f2 g1e3 a1b3 c2b3 h1f2 d1b3 g2g4 g1g4 g1a7 d2e3 b1b3 c2e3 f2d3 d2a5 d1e3 f2f6 f1f2 d1e3 c1b3 d2e3 c2e3 h2h8 g4f6 d2d3 b2d3 c1b3 f6h8 c2e3 b2b3 g2e3 a1a5 f1f6 c1e3 f2e3 h2g4 g2f2 a1a5 e1a5 e2e3 h1h8 g2g4 d1d3 a1a7 c1d3 e2g4 h2h8 g1g4 f2g4 d1g4 d1d3 f1d3 c1b3 f3f7 h2e2 a2b3 f2f6 b2h8 d1f2 f2f6 f1e2 g4d7 g1e3 g1a7 a3a7 d2e3 d1b3 d1d3 g2e3 h1c1 a2d5 b2a3 b4b5 d1c3 c1b2 d2d7 d1b3 b5d7 e5d7 c1b3 d1b3 b3b5 b1b3 a1c3 b1b2 h1h3 h2e5 a2a3 c2b4 f4f6 d1d7 h2f4 d2b4 b4d5 d1d7 g2d5 b1a3 f1h3 e1e5 c2a3 f1b5 b1b3 g1h3 a2d5 a2b4 c2a3 e2c3 c1f4 e1e5 b2a3 d1b3 a2d5 g2d5 a3b5 a1e5 g2d5 d5d7 e1f2 h2h5 a2a3 b2e5 a2b3 b1b4 h3d7 h2h5 a1f6 e1b4 a1a3 e2e5 d2f4 f2f4 a2a3 f1f2 c1c3 a1c3 b1c3 a1c3 c2b4 a1e5 g2h3 d1d3 e1e3 f2h3 e1c3 c1b2 c2a3 b3d5 g5g6 a4a5 a5a6 f4g5 g6h5 h4h5 h5h6 a6a7 g3g4 g6g7 h6h7 a3a4 h2h3 c5b6 b8a8 g7g8 a7a8 d2c3 e1d1 h7h8 h3h4 a2a3 h5g5 b3b4 g5f5 f5f4 b2b3 h1g1 c3b4 e1e2 c5c6 c4c5 c3c4 g4g5 f1e2 b7b8 b6b7 d1c1 f5g6 d4c5 d2e3 g8h8 a1a2 d1d2 h8e8 d1e1 h1h2 f7f8 b4b5 d7d8 h5g6 b4a5 c1d2 e2d2 d2e2 g4h5 e3d4 c1d1 b5b6 g8f8 b1c3 f5f6 g7f8 f1e1 d4e5 h8g7 a8a7 e4d5 c6c7 e4f5 g6h7 e1d2 e7e8 e6e7 c7c8 f2g2 e2f2 f4f5 h2h1 e7d8 e5e6 d6e7 h7g8 h5e2 g2f3 c1b2 g8h7 e8d8 d2c1 f6f7 e6d7 e4e5 f3f4 c5b4 b4c5 h8g8 f7g8 e2e3 f8e8 h6d6 a1b1 f8g8 c3d4 d5c6 d2d3 e2d1 e2f3 f2f3 b2c3 e3e4 e7f8 f3g4 b7c8 c7b8 e3d3 c2c3 c4b5 a1a3 g7h8 d8e8 f4e5 g1h1 g2g3 h8h7 c8b8 d5d6 b7a8 d2d1 e2d3 g5h6 g6f7 f7e8 d5e6 c6d7 g1g2 d1c2 e1f1 d7e8 h2h4 e8f7 d6d7 d3e3 g3f4 e5d6 a2a1 g3h4 c2d2 a7b8 e8f8 d1e2 c4d5 c6b7 c8d8 h6h5 e3d2 b1a1 b8a7 h4g5 a8b7 c5d6 c7d8 e8e7 d3c4 g8f7 c2c4 h6g7 g2f1 g1f3 e5d4 h1h3 e3f4 f3e4 c8d7 h3h2 d8c7 g7f7 a2b2 b6c5 g2h2 f1g2 c4c3 d3d2 a1b2 d3e2 f6g7 e7d6 d8d7 c1e3 b6c6 a2a4 f6e5 a6b6 a2b3 f3e2 d7c8 b6a7 e4d4 g5f6 a8b8 e2f1 d6c5 b2a3 e2e1 b8c8 f8f7 d3d4 d6c7 g2f2 b3a3 b1c1 b4b3 b4c3 f1f2 c1b1 d3e4 d7e6 f7g7 d8e7 d2d4 d5e4 d7c7 b3a4 b5a6 e5f6 d4e4 g4f5 g3h3 f1g1 a3b3 e6f7 e2e4 h3g3 f8g7 h3g4 c3d2 a4b5 b2a2 e5d5 g1f1 c1c2 h4g3 d2c2 d4e3 b5c6 b3c4 h1g2 h7g6 f2f4 g6f5 g7g6 c7d6 f4f3 f5e6 f6f5 e1f2 d2e1 f2g3 b2a1 a5b6 e7f7 d6e6 a7b6 f5g4 f3e3 c6d5 c7d7 e5f4 f7f6 e7d7 e8d7 h2g1 c2d3 c2b3 h5h4 e3e2 g4f3 d5e5 f4e4 a3b4 a3a2 d7e7 c5d4 a5b5 b3c2 a8a6 c2b2 g6h6 g7f6 f2f1 c4d4 f2e2 f7e7 f3d1 b5c5 c8b7 g8g7 f6e7 b8c7 f2e1 c8c7 e7f6 h8a8 g2h1 f7g6 a3b2 h6g6 d5d4 c6d6 d4d3 f2e3 b2b4 d1f3 c3d5 b7c6 b5a5 g4g3 b6c7 a7b7 g1h2 h2g3 d7d6 e4d3 h4h3 a1d1 c3d3 g1h3 f7e6 g2g1 f6g6 e3f2 e3f3 b5c4 b6a5 d4c4 a6b7 g1e2 f3f2 e6f5 c2c1 c3c2 h7h6 h6g5 a8h8 g3g2 h4g4 c2b1 b6b5 f4g3 e6d6 g5f4 e6e5 d5c4 a7a6 b1d2 d4c3 a4b4 b1b2 b2c1 g5g4 b3a2 g2h3 d3c2 d1b1 f3g3 a4a3 b2b1 b3b2 h2g2 c3e4 a5a4 f4g4 c6b5 c7b7 b4a3 e7e6 b7b6 e6f6 f3d5 d5c5 g6g5 g6f6 b1a2 e4e3 b2c2 h7g7 d6d5 d6e5 g4h3 c8h3 b3c3 f1d3 a8c6 b1d1 d3c3 f3g2 g3f3 c3b5 h3g2 c5c4 d7c6 b4d2 a5b4 f3e5 f4e3 b1a3 b5a4 b4a4 d3f5 b8b7 g7h6 g1f2 e4f4 f5e4 d2f4 g3h2 b4c4 f8h6 c3b2 f6g5 d1d3 a3a1 c6c5 c4b4 c5b5 f2g1 h3h1 d4d5 e5e4 h7b7 g4f4 g7h7 g5h5 a2b1 d5e7 g1g3 g5h4 h6f8 c2d1 b5b4 b6a6 c4b3 h5g4 c3b3 f1c4 c5d5 a1c1 c8e8 h3g5 f5g5 e4e2 g4h4 f5e5 f6d8 e5f5 b5c7 b7a7 h3f3 g5e7 c5e7 d8f6 e2d4 a8c8 h1f1 e8e6 f3g5 a4b3 c7c6 f3h5 a5c7 h7f5 a1a7 d4f4 g3f2 e7c8 b7b3 g7g5 g5f7 b7a6 b1c2 d6c6 f3g1 f3d4 d1a1 a7c5 h2f2 c7b6 a6a5 e8c8 e6d5 f7d8 e4f3 b8b4 g3e3 d1f1 g8e8 h5h7 f6e6 f6h8 c3b1 e8h8 h8e5 e3g5 h8f8 d8a8 a8a1 a5d8 f5d7 c6b6 c8a8 c1a3 a6b5 a3c1 d6f4 g2g4 d2e4 e1h1 e2c2 h4f4 f8a3 h8d4 e8g7 h6f4 g7g3 f4d6 a8d5 h2e2 f1f3 d8g8 a7g7 c8b6 e4c6 d8b6 e3c5 f8d6 f1h1 a1h1 g1e1 h3g1 f8f6 b3b8 f4d4 e3e1 f4d2 g6e7 c1e1 a1a8 d8b7 g4e2 a8h1 f8h8 d4e6 c1a1 f5h7 h7f7 c4d3 a1e1 c2e4 b7c7 e2c4 b8e8 g8g6 e6d8 d8f8 h1e1 f4h2 g5h7 d3d5 f4h6 a8e8 e1g1 c4e2 f3h2 g5d8 a8c7 d1g4 e5h8 e5f3 f6e8 d5f7 f7h8 d1h5 e1a1 b6d7 e7b4 h1h7 e8c6 a3a5 e4d6 a6h6 a3f8 a3c3 b8d8 d6f8 h2f4 e4f6 h3f1 e8g6 c3c5 g8e6 d8a5 a2d2 h7f8 h3f5 h8f7 c7e8 e5d7 e8a8 f3f7 h1a8 g8a2 b6a8 d4f6 a4c4 e1e4 c7a8 f8c8 h8h6 h5h8 f3f1 f1f4 c1f4 b8d6 d5f5 e4g6 h5f3 d2f1 h2g4 a3b5 a3c2 g6e6 c6f6 f8e7 a8g8 a2c2 e1b1 f8h7 f4h4 c8h8 h8a1 f8b8 g6e8 a8g2 e6e8 a8b6 e5c7 e8f6 c6e8 d4c6 d1b3 e7g7 e4c4 g7d4 e2e5 d7h3 d7f5 c1h6 a7e7 f2e4 h3d3 f1h3 f3f5 c6a8 c6e6 d7f7 a1a4 f8c5 e6c4 e2f4 d7f8 e4g2 b7c5 e5g7 a1d4 h3h5 d2f2 e3c3 f8g6 a3b1 b7d7 e6g6 h1c1 d3d6 a1f1 g1a7 e8h5 b8h8 e3b3 h1e4 b1f1 d6f5 a4a6 f1c1 h2b8 b4d6 c1c3 a6b4 a1c3 f7b7 f4f6 b3b7 h8g6 g3g5 d4e2 f7e5 a8f3 c3e5 e8b8 d2a2 h8c8 d2g5 e6g8 d4d6 c2a2 a8a4 c8c6 d8e6 g2e4 a8f8 a1h8 d4f2 f8d8 b8g3 b4a2 e7g5 d7b7 c5f8 d6d2 a7d7 e4g3 a8a3 f7d5 g7f5 h5f7 e4d2 h3f4 f3d2 d4b6 b1h1 a3c4 f1d1 g2a8 f5d4 f4g6 e7e5 b2d4 h1d1 b4b7 g8b8 d2f3 d5e3 c4a2 f3c3 a2h2 f5h4 e8e1 a3h3 f2h2 g5e3 d3b3 d6e4 c8c2 h8h1 e3h3 d5d8 c4d2 h6f7 g8g1 a5c3 f6e4 c7a7 b4d4 e7c6 h8d8 f5f3 c8e6 c8c4 e7c7 c8c5 c3f6 h5f5 a6a4 h4f3 g2e2 a2e6 d1h1 f1b1 e5e2 b8b5 g4g2 b6d4 d3b5 g8d5 c1c8 c4c1 g4e6 d2h2 d8d4 g5d2 h5e8 c7a5 a7f7 h7e4 a4c3 h1h6 e1c1 h8h3 d2a5 d8g5 d2c4 g6d3 f8b4 a8d8 b3e3 g6g3 c4d6 g3d6 f4f1 h3a3 h8h4 e8g8 g3f5 a6e2 c5a4 c4f4 f3a8 e2b2 e4c3 e1e3 d8h4 c5d7 e6c8 d5f4 e5e3 d4h8 d1g1 d8f7 f6d5 g6c2 d6b8 d3f3 c6a6 f5e3 e5a1 c5e3 h3f2 d3d1 d8h8 g6e4 c6d8 c8f5 d2b4 e7g8 b1b4 f1e3 e4h4 b7b4 g7d7 e4c2 f3h4 d2b2 a5a7 f2d4 a5c5 c2b4 e6e4 c3f3 c1g1 b5d6 e8d6 h1h5 c3e3 d7d5 d5f6 c1g5 f2d2 b1g6 f4c7 h8b2 g8c8 d6h6 f5h3 h4h2 d3d7 d5g5 d5f3 a6d3 e7c5 f4e6 c7e6 e3g4 b5d7 d5a8 e8a4 d4f3 a4a2 e1e6 c4f1 b6b8 a2e2 d6e8 f7d6 d5h5 e2c3 b3d3 g8b3 b3d5 c8e7 c2a4 d5d1 a7d4 d1d4 c4c2 d8d1 c8f8 d7e5 e2h2 a6c6 f5c5 d8d2 d4g7 g4h6 f3d3 f3h3 c4g8 e2b5 h6h8 a8a5 e2g2 f5d5 f7f5 e7a7 c7d5 e5d3 d3g6 f7c7 b2d2 b5b8 f6c6 c7e7 e5h2 d7f6 c3e2 d8b8 a1a6 e7f5 h1a1 d5b3 d1d5 h7b1 f4f2 f7d7 h4f6 b2e2 a2b4 d2b1 d4b2 c8g8 c6d4 c4c6 c6c8 f5f8 d8d6 d4a1 f1a1 b5b1 d7g7 g1d1 e2g1 g8g5 g4e3 g8d8 h8h5 g7e8 h8b8 e4f2 c3a4 c8c1 g5e6 h8f6 e4g4 g3d3 e6c5 d4c2 d5d2 b8g8 g3g1 h6c6 g4g6 a5d2 a4c6 b2g7 a1c2 g2c6 h5d1 e3d5 g3g8 b4a6 h1h8 e6g4 d3e5 c3h8 b1b3 e5b8 c3a5 e7h7 g5g3 d4b4 g4g7 h6c1 e2g4 f6h4 a1a5 g1g4 d3g3 e5f7 h1h4 c2d4 e5c4 f6h6 b7e4 d2h6 f5c2 e4c5 e3g3 d8c6 d1a4 c2e3 c3a1 c5a3 f5g7 b4b6 b5d3 b3b5 b7e7 e3h6 d6c8 d6g3 e4e1 d5d7 c4a6 f5d3 b4b8 g5d5 g8f6 g8e7 f1b5 d4d8 f2f5 b6b2 h5h1 a5d5 e5b2 d1e3 a5a1 a3d3 e4a4 a1g7 d1f2 f6d4 f4e2 e3c2 b1e1 h2d2 d8d3 h7d7 e3f5 b3a1 b3g8 e5e7 d5h1 e5c6 h1b1 a4b6 a6c4 b2f6 g1e3 d1d8 h6e6 c8a6 c6e4 c4c8 a5a8 a2a5 c6a4 e5g4 f3a3 b8b6 d7d2 d5b6 c7c5 h7g5 f4g2 a4c5 d5b5 a3e7 d6d8 e7b7 g3e5 d4d1 d7d4 d4d7 d5b7 e2g3 a3a8 c7e5 c5c3 g5e4 f4b4 b7h7 g3e1 e2h5 d4d2 c1a2 d7b5 b6f2 e5g3 g4f6 e5e1 b4e7 h2h7 a7g1 d4h4 d3b1 h5e5 d8d5 e3f1 b5f5 f5f1 b6a4 e2c1 b6b3 d4g4 e4e7 g1b1 h3e3 e6c6 g4d4 b8e5 e3c1 d5d3 b5e8 e5c3 e1e7 h5d5 c3g7 b4c2 g2g5 g5b5 c5c7 a4c2 f7h7 c7f4 c5b3 b2f2 a2a7 h7c7 c2e2 f7c4 b1d3 a3c5 f4c1 c7g7 c5a7 g8a8 b1h7 c3d1 a7a5 b2e5 c4e5 f3h1 b4g4 g2e1 d7g4 d4g1 c2c5 e6f4 a4e4 e1g3 e6b6 h2c2 c2c7 d6f6 e6d4 f5c8 c2e1 b7f3 a3d6 a4a1 b4f4 e7e2 g2g8 a1g1 a7e3 d6a6 b3b1 c3c8 f2a7 c6e7 a5e5 g4d1 b3c1 e7d5 h6d2 b2b5 b5d5 e8b5 b3c5 f2g4 h1b7 f5g3 c7h7 c4e4 h1f3 a3a6 g7b2 c5e4 c3a2 d1d7 h7h4 a2c4 b4b2 e1e8 b5a3 b4f8 e5c5 e7g6 a4f4 b7b1 f5h6 h3e6 g7e5 h2b2 d2b3 c1f1 a6c8 c7a6 d4b5 a7a3 g7h5 c2g6 d5c7 g8c4 f6f8 f5b1 a4a8 c5c2 f1a6 e8e4 c5f2 a2d5 d7b8 h4f5 c5e5 c4b2 e4b4 e6c7 h4h8 c6b8 e3c4 g7e7 e6h3 c3c1 c6e5 b2b6 g7c7 d6f7 f6g8 f8f5 f6f3 h2e5 h4e4 d7a7 f5a5 d5g2 c4e6 f8a8 g2g7 c2a1 a7c7 a2f7 d6d4 h4e1 h5f4 b1g1 f1f6 b1b8 a4h4 a4d4 f2b2 a7h7 g2f4 h3h8 f6f4 e3b6 h7d3 b6d8 f1d2 d6h2 g4f2 f5e7 b3f3 c2g2 d1d6 a2f2 c8g4 f5h5 g1d4 g2b7 e4g5 e6e3 e2e6 b1f5 b5c3 b3h3 e2e8 b1b5 b7d8 g6h4 h7e7 g1a1 f6d6 c1d3 f7a2 a1e5 f2h4 e7h4 h7h1 f2d1 b3e6 g5h3 e5e8 e6f8 d5a5 c3g3 d3a3 c5b7 b5b3 e2a2 a6a1 f4f8 f2f7 a6f6 b2d1 g6b1 h6f6 h6a6 c2c8 b8b3 e6e2 b6b4 c1c4 a5f5 f4h3 c2f2 a5a2 c3h3 c5f5 b3b6 b5a7 d6b7 b4d5 f6f2 g7c3 e1e5 a3g3 a6a3 f1f5 g4c4 e5g6 a8a2 e4a8 a6e6 e3d1 c3e1 a6g6 f7h5 b7g7 e3a3 g5g2 h5h2 a4d1 e3e6 f4d5 d2d8 g8g2 c4e3 f6b2 g4d7 g6f8 b7b5 a4e8 b3d2 e6h6 b8h2 d3h3 f4c4 b8f4 f5f7 g1g7 c6f3 b3g3 g3h1 b6c4 g6g4 a3e3 d4f5 a7f2 h2h8 b7d6 c5c8 c6c4 c8c3 f6h7 e3e5 e6g7 f4b8 b4c6 b3d4 g4h2 a8e4 h5h3 c6h6 f6a1 d5a2 g6d6 b2h8 c2c6 b3a5 a6f1 g6c6 f3b7 g7a7 g7e6 e1b4 h6h4 a5g5 f3f8 g3g7 d3c5 h1c6 d6b4 g3h5 a7a4 f6f1 c2h2 g2a2 b6f6 g3f1 b8f8 c4c7 f8f3 b5d4 c4b6 c1e2 b3f7 e1c3 d3f1 b4d3 a6a8 h6h2 h4d8 f7h6 b7g2 d6b6 d6g6 g4e4 h2h6 g6g1 c4a4 f8e6 f5b5 c5a6 f2h3 d4a7 c3c6 e8e3 e6a2 a4g4 b2g2 a6a2 h7a7 a1b3 h4h6 c4g4 b6e3 f2c5 b8c6 e2a6 e8e5 a4a7 f8d7 c7f7 g6b6 f3f6 a6d6 c6a5 g4e5 g4g8 h4h1 b3d1 f1g3 f4f7 b8d7 f3c6 e1g2 f8f4 g6h8 a6c7 f2d3 b2b8 b1b6 b6e6 a2c1 h6g4 d7c5 e3e8 a5b3 a7c6 e7a3 e1c2 h3d7 g1g5 g5g8 b1e4 b6g1 b1b7 h4f2 b7f7 f7f3 f4h5 e4e8 c6g6 e5g5 c6h1 f2c2 h4d4 g1c1 f5f2 c2a3 b2c4 d5c3 a7b5 h7h3 e1a5 e6b3 g2c2 e3g2 c7c3 c6c2 a7a2 h3b3 d4a4 b8b2 d6d1 f3e1 e4e6 g2d2 c7c4 h7h5 c7g3 c5a5 h8h2 h5b5 g3e2 b6c8 f1f7 h2a2 d6a3 g4c8 g8g4 f6c3 h4h7 d1c3 g2d5 c1c6 h2c7 g7g4 g5g7 a5c4 g1g6 e6g5 c6c3 e1f3 g2e3 b5e5 f7f4 g1g8 e4b1 f7f2 c5e6 e2e7 e5h5 c2f5 d6d3 c5c1 e4b7 e4h1 f4d3 d7b6 b5e2 a2c3 b4b1 a1f6 f2f8 g3b3 c7c1 h4g2 b8a6 c4a5 h1f2 h2f3 f2f6 d3c1 e7e1 d3d8 g4g1 c1b3 a5c6 d3e1 c5g5 a6c5 f2a2 b2h2 h6h1 c3a3 g6g8 d1b2 f8f1 h7f6 e8e2 d6b5 c4f7 d3a6 h6h3 c5d3 b7a5 g3e4 f1f8 g5e5 a5e1 g5c1 g5a5 f3b3 e6a6 h4e7 h2h5 g5c5 g8g3 d3f4 c6a7 c7h2 g3g6 f4a4 e3g1 c6g2 e7e3 d6c4 d7d1 b5b2 b7d5 f6d7 a3f3 h5f6 b2b7 a2g2 h4c4 c1c5 a5b7 b6b1 c8d6 a4d7 e3a7 d4b3 g6e5 d2g2 d2d5 c1c7 g6g2 a5a3 c6b4 b7h1 b5b7 d3f2 h5c5 e1h4 f6g4 b5h5 c7b5 b6d6 f7a7 b4e1 h4a4 d8c8 c4a3 f5d6 b6d5 f6a6 g7g1 h6g8 b7b2 h8c3 f7g5 f2h1 g6f4 c5g1 d2d7 h3h7 h2f1 e8c7 e6e1 g3c3 g1c5 b6g6 g1b6 a2g8 a2a8 h1g3 d3b4 e3e7 b8b1 g3b8 h5a5 d3b2 a4b2 a5h5 h4b4 h7h2 c5h5 b5f1 h6e3 g7g2 a6b8 f7b3 h3c8 g5f3 f6h5 d7h7 c3c7 h1d5 h7c2 e7e4 g4a4 d3h7 c1h1 a3a7 g6a6 h5g3 a7a1 b6h6 b4e4 b2a4 h3c3 g3c7 h2d6 d5g8 g7b7 f8f2 c6c1 b2d3 e4h7 b5g5 d2d6 h4g6 g7a1 f1h2 d5b4 c7c2 e1d3 h6f5 g2g6 g8h6 e5b5 c8a7 e5a5 f7f1 g2b2 a2a6 g3a3 g4b4 f2b6 h6b6 f6b6 d7a4 c4h4 g2h4 g5g1 h3h6 h5g7 b4h4 c2h7 a7c8 d7d3 ",
        };
        Random random=new Random();

        int color=1;
        int seed=123;
        if (argv.length==2) {
            color="wb".indexOf(argv[0]);
            seed=(int)Long.parseLong(argv[1]);
        }
        random.setSeed(seed);
        int idx=random.nextInt(list.length);

        while (true) {
            for (int s = 0; s < list[idx].length(); s+=5) {
                String uci=list[idx].substring(s,s+2)+" "+list[idx].substring(s+2,s+4);
                if (color==1) {
                    // black: then rewrite uci for black
                    uci=uci.substring(0, 1)+"x87654321".indexOf(uci.charAt(1))+" "+uci.substring(3, 4)+"x87654321".indexOf(uci.charAt(4));
                }
                System.out.println(uci);
            }
        }
    }
}

Bob Genom

Posted 2019-10-29T10:44:49.450

Reputation: 846

3

Memorizer

import sys
import random
from functools import lru_cache


board = [
    [{"R"},{"K"},{"B"},{"Q"},{"k"},{"B"},{"K"},{"R"}],
    [{"P"},{"P"},{"P"},{"P"},{"P"},{"P"},{"P"},{"P"}],
    [set(),set(),set(),set(),set(),set(),set(),set()],
    [set(),set(),set(),set(),set(),set(),set(),set()],
    [set(),set(),set(),set(),set(),set(),set(),set()],
    [set(),set(),set(),set(),set(),set(),set(),set()],
    [set(),set(),set(),set(),set(),set(),set(),set()],
    [set(),set(),set(),set(),set(),set(),set(),set()]]

_, color, seed = sys.argv[:3]
random.seed(seed)

pawns = [(i,j) for i in range(8) for j in range(4)]

colnames = "abcdefgh" if color == "w" else "hgfedcba"
rownames = "12345678" if color == "w" else "87654321"

def coord2code(col, row):
    return colnames[col] + rownames[row]

def move(col1, row1, col2, row2):
    if (col1, row1) not in pawns and 0 <= col2 <= 8 and 0 <= row2 <= 8:
        pass
    try:
        print(" ".join((coord2code(col1, row1),coord2code(col2, row2),"q")))
        for type in board[row1][col1]:
            if (col2,row2) in getmoves(col1,row1,(type,)):
                board[row2][col2].add(type)
            if "P" in board[row2][col2] and row2 == 8:
                board[row2][col2].add("Q")
        pawns.append((col2,row2))
    except IndexError:
        pass

def pawncapture(col, row):
    if random.getrandbits(1):
        move(col, row, col+1, row+1)
        move(col, row, col-1, row+1)
    else:
        move(col, row, col+1, row+1)
        move(col, row, col-1, row+1)

def spycheckmove(col1, row1, col2, row2):
    move(col1,row1,col2,row2)
    move(col2,row2,col1,row1)

def protect_middle(adventure = True):
    move(4,3,3,4)
    move(3,3,4,4)
    move(2,2,3,3)
    pawncapture(4,4)
    pawncapture(3,3)
    pawncapture(2,2)
    pawncapture(5,2)
    spycheckmove(2,2,3,4)
    move(2,1,2,2)
    spycheckmove(5,2,4,4)
    move(5,1,5,2)

@lru_cache()
def getmoves(col, row, piece_types):
    return list(buildmoves(col, row, piece_types))

def buildmoves(col, row, piece_types):
    if "K" in piece_types:
        # Knight moves
        for x in (1, 2, -2, -1):
            if x+col >= 0 and x+col <= 7:
                for y in (2//x, -2//x):
                    if y+row >= 0 and y+row <= 7:
                        yield (x+col, y+row)

    if "P" in piece_types:
        yield (col+1,row+1)
        yield (col+1,row+1)
        yield (col-1,row+1)
        yield (col-1,row+1)
        yield (col+1,row+1)
        yield (col+1,row+1)
        yield (col-1,row+1)
        yield (col-1,row+1)
        yield (col+1,row+1)
        yield (col+1,row+1)
        yield (col-1,row+1)
        yield (col,  row+1)
        yield (col,  row+1)

    if "k" in piece_types:
        yield (col+1,row)
        yield (col-1,row)
        yield (col, row+1)
        yield (col, row-1)
        yield (col-1, row-1)
        yield (col-1, row+1)
        yield (col+1, row-1)
        yield (col-1, row+1)        
        yield (col+1,row)
        yield (col-1,row)
        yield (col, row+1)
        yield (col, row-1)
        yield (col-1, row-1)
        yield (col-1, row+1)
        yield (col+1, row-1)
        yield (col-1, row+1)

    if "B" in piece_types or "Q" in piece_types:
        # Bishop moves
        for x in range(1,8):
            if col+x <= 7:
                if row+x <= 7:
                    yield (col+x, row+x)
                if row-x >= 0:
                    yield (col+x, row-x)
            if col-x >= 0:
                if row+x <= 7:
                    yield (col-x, row+x)
                if row-x >= 0:
                    yield (col-x, row-x)

    if "R" in piece_types or "Q" in piece_types:
        # Rook moves
        for x in range(1,8):
            if col+x <= 7:
                yield (col+x, row)
            if col-x >= 0:
                yield (col-x, row)
            if row+x <= 7:
                yield (col, row+x)
            if row-x >= 0:
                yield (col, row-x)

move(4,1,4,3)
protect_middle()
move(4,0,4,1)
move(4,1,4,2)
move(3,1,3,3)
protect_middle()
move(1,0,2,2)
protect_middle()
move(6,0,5,2)
protect_middle()

while True:
    a = random.choice(pawns)
    piecetypes = board[a[1]][a[0]]
    if not piecetypes:
        continue
    b = random.choice(getmoves(a[0],a[1],tuple(piecetypes)))
    move(a[0], a[1], b[0], b[1])

Is somewhat smart about random moves, also does a little dodging to avoid BluntV1 and Scholar

famous1622

Posted 2019-10-29T10:44:49.450

Reputation: 451

pawncapture's if statement does nothing :P – Spitemaster – 2019-11-04T18:53:53.340

@Spitemaster I thought I checked everything D:, welp, it's stuck now – famous1622 – 2019-11-04T18:55:11.277

3Stuck? Easy enough to fix. It's perfectly fine to edit/update it. – Spitemaster – 2019-11-04T19:04:34.047

I do think remembering where your pieces are is the next evolution in blind chess bots, but this bot doesn't (yet) use it in a way that helps with winning. Some thoughts: It needs to somehow reach a point where it's sure a piece is no longer where it used to be, and it needs to actively untangle pieces from each other (i.e. if the king is sitting where a pawn should be - my Prickly has no end of trouble with this). – Brilliand – 2019-11-04T22:46:23.470

@Brilliand I agree, one things is you can make moves that confirm a piece won't be a certain type (for example moving a knight to a space where another one of your pieces definitely isn't is always possible (barring check), therefore you know that the origin isn't a knight anymore) – famous1622 – 2019-11-05T14:38:57.683