import ae.sys.data; import ae.sys.datamm; import ae.utils.array; import ae.utils.meta; import std.algorithm.iteration; import std.algorithm.searching; import std.conv; import std.exception; import std.file; import std.stdio; import std.string; import driver; import game; import gamelogic; import graph; import packing; static struct GraphDriver { static GraphDriver create() { GraphDriver d; d.scores = mapFile(scoreFileName(), MmMode.read).asDataOf!PackedScore; return d; } TData!PackedScore scores; enum interactive = false; void log(scope string delegate() message) /*nothrow @nogc*/ {} Score recurse(const ref Game game) nothrow @nogc { // return expand.expand(game, &this); return scores[game.packGame()].unpackScore; } alias GetScore(T) = Score delegate(T) /*nothrow @nogc*/; // alias choice = graphChoice!GetScore; bool topLevel = true; string bestMove; Score bestScore; Score choice(ChoiceMode mode, T)( scope string delegate() description, scope Score delegate(T) /*nothrow @nogc*/ getScore, scope string delegate(T) getDescription, scope const(T)[] items... ) //nothrow @nogc { alias impl = graphChoice!GetScore; if (topLevel) { static if (mode == ChoiceMode.best && (is(T == Move) || is(T == Bet))) { topLevel = false; scope(exit) topLevel = true; bestScore = 0; foreach (item; items) { auto score = getScore(item); if (score > bestScore) { bestScore = score; bestMove = getDescription(item); } } return Score.nan; // We got what we needed } else assert(false); } else return impl!(mode, T)(description, getScore, getDescription, items); } alias gameOver = graphGameOver; } void main() { Game game; auto lines = "game.txt".readText.split1("\n"); foreach (i, line; lines) { if (i % 3 == 2) enforce(line.length == 0, "Expected empty line"); auto character = i % 3 == 0 ? Character.player : Character.dealer; Bet bet = Bet.minimum; if (character == Character.player && line.skipOver("M")) bet = Bet.maximum; auto cards = line.strip.split.map!(to!Card); // if (character == Character.player) // enforce(cards.length, "Unexpected empty line"); foreach (card; cards) { enforce(game.deck[card], "No more cards with value %d".format(card)); game.deck[card]--; if (game.deck[].sum == 0) game.deck = fullDeck; // shuffle if (character == Character.player && i + 1 == lines.length) { assert(character == Character.player); game.state = Game.State.playerTurn; game.bet = bet; game.hand.numCards++; game.hand.totalValue += card; } } } if (lines.length % 3 == 1) { loadTables(); auto driver = GraphDriver.create(); expand(game, &driver); writefln("Best move: %s (%s%%)", driver.bestMove, driver.bestScore * 100); } else writeln("OK (awaiting data)"); }