#include "calc_tables.hpp"
#include <pbn.hpp>
#include <solve_board.hpp>
#include <api/solve_board.hpp>
#include <solver_if.hpp>
#include <system/memory.hpp>
#include <system/scheduler.hpp>
#include <system/system.hpp>
ParamType cparam;
extern System sysdep;
extern Memory memory;
extern Scheduler scheduler;
auto calc_all_boards_n(
Boards * bop,
SolvedBoards * solvedp) -> int;
auto calc_single_common(
const int thrId,
const int bno) -> void;
auto calc_single_common_internal(
SolverContext& ctx,
[[maybe_unused]] const int thrId,
const int bno) -> void
{
FutureTricks fut{};
Deal deal = cparam.bop->deals[bno]; deal.first = 0;
START_THREAD_TIMER(thrId);
int res = solve_board(
ctx,
deal,
cparam.bop->target[bno],
cparam.bop->solutions[bno],
cparam.bop->mode[bno],
&fut);
if (res == 1)
cparam.solvedp->solved_board[bno].score[0] = fut.score[0];
else
cparam.error = res;
for (int k = 1; k < DDS_HANDS; k++)
{
int hint = (k == 2 ? fut.score[0] : 13 - fut.score[0]);
deal.first = k;
res = solve_same_board(ctx, deal, &fut, hint);
if (res == 1)
cparam.solvedp->solved_board[bno].score[k] = fut.score[0];
else
cparam.error = res;
}
END_THREAD_TIMER(thrId);
}
auto calc_single_common(
const int thrId,
const int bno) -> void
{
SolverContext ctx;
calc_single_common_internal(ctx, thrId, bno);
}
auto copy_calc_single(const vector<int>& crossrefs) -> void
{
for (unsigned i = 0; i < crossrefs.size(); i++)
{
if (crossrefs[i] == -1)
continue;
START_THREAD_TIMER(thrId);
for (int k = 0; k < DDS_HANDS; k++)
cparam.solvedp->solved_board[i].score[k] =
cparam.solvedp->solved_board[ crossrefs[i] ].score[k];
END_THREAD_TIMER(thrId);
}
}
auto calc_chunk_common(
const int thrId) -> void
{
vector<FutureTricks> fut;
fut.resize(static_cast<unsigned>(cparam.no_of_boards));
int index;
schedType st;
while (1)
{
st = scheduler.GetNumber(thrId);
index = st.number;
if (index == -1)
break;
if (st.repeatOf != -1)
{
START_THREAD_TIMER(thrId);
for (int k = 0; k < DDS_HANDS; k++)
{
cparam.solvedp->solved_board[index].score[k] =
cparam.solvedp->solved_board[ st.repeatOf ].score[k];
}
END_THREAD_TIMER(thrId);
continue;
}
calc_single_common(thrId, index);
}
}
auto calc_all_boards_n(
SolverContext& ctx,
Boards * bop,
SolvedBoards * solvedp) -> int
{
cparam.error = 0;
if (bop->no_of_boards > MAXNOOFBOARDS)
return RETURN_TOO_MANY_BOARDS;
cparam.bop = bop;
cparam.solvedp = solvedp;
cparam.no_of_boards = bop->no_of_boards;
scheduler.RegisterRun(RunMode::DDS_RUN_CALC, * bop);
for (int k = 0; k < MAXNOOFBOARDS; k++)
solvedp->solved_board[k].cards = 0;
START_BLOCK_TIMER;
for (int bno = 0; bno < bop->no_of_boards; bno++) {
calc_single_common_internal(ctx, 0, bno);
if (cparam.error != 0)
return cparam.error;
}
END_BLOCK_TIMER;
solvedp->no_of_boards = cparam.no_of_boards;
#ifdef DDS_SCHEDULER
scheduler.PrintTiming();
#endif
return RETURN_NO_FAULT;
}
auto calc_all_boards_n(
Boards * bop,
SolvedBoards * solvedp) -> int
{
SolverContext ctx;
return calc_all_boards_n(ctx, bop, solvedp);
}
int STDCALL CalcDDtable(
DdTableDeal tableDeal,
DdTableResults * tablep)
{
Deal dl;
Boards bo;
SolvedBoards solved;
for (int h = 0; h < DDS_HANDS; h++)
for (int s = 0; s < DDS_SUITS; s++)
dl.remainCards[h][s] = tableDeal.cards[h][s];
for (int k = 0; k <= 2; k++)
{
dl.currentTrickRank[k] = 0;
dl.currentTrickSuit[k] = 0;
}
int ind = 0;
bo.no_of_boards = DDS_STRAINS;
for (int tr = DDS_STRAINS-1; tr >= 0; tr--)
{
dl.trump = tr;
bo.deals[ind] = dl;
bo.target[ind] = -1;
bo.solutions[ind] = 1;
bo.mode[ind] = 1;
ind++;
}
int res = calc_all_boards_n(&bo, &solved);
if (res != 1)
return res;
for (int index = 0; index < DDS_STRAINS; index++)
{
int strain = bo.deals[index].trump;
for (int first = 0; first < DDS_HANDS; first++)
{
tablep->res_table[strain][ rho[first] ] =
13 - solved.solved_board[index].score[first];
}
}
return RETURN_NO_FAULT;
}
int STDCALL CalcAllTables(
DdTableDeals const * dealsp,
int mode,
int const trumpFilter[5],
DdTablesRes * resp,
AllParResults * presp)
{
Boards bo;
SolvedBoards solved;
int count = 0;
bool okey = false;
for (int k = 0; k < DDS_STRAINS; k++)
{
if (!trumpFilter[k])
{
okey = true;
count++;
}
}
if (!okey)
return RETURN_NO_SUIT;
if (count * dealsp->no_of_tables > MAXNOOFTABLES * DDS_STRAINS)
return RETURN_TOO_MANY_TABLES;
int ind = 0;
int lastIndex = 0;
resp->no_of_boards = 0;
for (int m = 0; m < dealsp->no_of_tables; m++)
{
for (int tr = DDS_STRAINS-1; tr >= 0; tr--)
{
if (trumpFilter[tr])
continue;
for (int h = 0; h < DDS_HANDS; h++)
for (int s = 0; s < DDS_SUITS; s++)
bo.deals[ind].remainCards[h][s] =
dealsp->deals[m].cards[h][s];
bo.deals[ind].trump = tr;
for (int k = 0; k <= 2; k++)
{
bo.deals[ind].currentTrickRank[k] = 0;
bo.deals[ind].currentTrickSuit[k] = 0;
}
bo.target[ind] = -1;
bo.solutions[ind] = 1;
bo.mode[ind] = 1;
lastIndex = ind;
ind++;
}
}
bo.no_of_boards = lastIndex + 1;
int res = calc_all_boards_n(&bo, &solved);
if (res != 1)
return res;
resp->no_of_boards += 4 * solved.no_of_boards;
for (int m = 0; m < dealsp->no_of_tables; m++)
{
for (int strainIndex = 0; strainIndex < count; strainIndex++)
{
int index = m * count + strainIndex;
int strain = bo.deals[index].trump;
for (int first = 0; first < DDS_HANDS; first++)
{
resp->results[m].res_table[strain][ rho[first] ] =
13 - solved.solved_board[index].score[first];
}
}
}
if ((mode > -1) && (mode < 4) && (count == 5))
{
for (int k = 0; k < dealsp->no_of_tables; k++)
{
res = Par(&(resp->results[k]), &(presp->par_results[k]), mode);
if (res != 1)
return res;
}
}
return RETURN_NO_FAULT;
}
int STDCALL CalcAllTablesPBN(
DdTableDealsPBN const * dealsp,
int mode,
int const trumpFilter[5],
DdTablesRes * resp,
AllParResults * presp)
{
DdTableDeals dls;
for (int k = 0; k < dealsp->no_of_tables; k++)
if (convert_from_pbn(dealsp->deals[k].cards, dls.deals[k].cards) != 1)
return RETURN_PBN_FAULT;
dls.no_of_tables = dealsp->no_of_tables;
int res = CalcAllTables(&dls, mode, trumpFilter, resp, presp);
return res;
}
int STDCALL CalcDDtablePBN(
DdTableDealPBN tableDealPBN,
DdTableResults * tablep)
{
DdTableDeal tableDeal;
if (convert_from_pbn(tableDealPBN.cards, tableDeal.cards) != 1)
return RETURN_PBN_FAULT;
int res = CalcDDtable(tableDeal, tablep);
return res;
}
void detect_calc_duplicates(
const Boards& bds,
vector<int>& uniques,
vector<int>& crossrefs)
{
return detect_solve_duplicates(bds, uniques, crossrefs);
}