diff --git a/.gitignore b/.gitignore index 3265db34..cd17f0ab 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ src/[Mm]akefile test/[Mm]akefile examples/[Mm]akefile +examples/*.js +examples/*.wasm test/dtest test/itest diff --git a/examples/AnalysePlayBin.cpp b/examples/AnalysePlayBin.cpp index c1929c6a..48f0ec7f 100644 --- a/examples/AnalysePlayBin.cpp +++ b/examples/AnalysePlayBin.cpp @@ -30,7 +30,7 @@ int main() char line[80]; bool match; -#if defined(__linux) || defined(__APPLE__) +#if defined(__linux) || defined(__APPLE__) || defined(__WASM__) SetMaxThreads(0); #endif @@ -62,7 +62,9 @@ int main() if (res != RETURN_NO_FAULT) { +#ifndef __WASM__ ErrorMessage(res, line); +#endif printf("DDS error: %s\n", line); } diff --git a/examples/Makefiles/Makefile_wasm b/examples/Makefiles/Makefile_wasm new file mode 100644 index 00000000..f2bce5e1 --- /dev/null +++ b/examples/Makefiles/Makefile_wasm @@ -0,0 +1,119 @@ +# This is a Makefile for the examples, +# for Mac and the clang compiler. + +# It does assume a Unix-like setup for some commands, +# but if you only want to call "make" with the default target, +# you should be OK. + +# If your compiler name is not given here, change it. +CC = em++ + +CC_FLAGS = -O3 -flto -mtune=generic + +# These flags are not turned on by default, but DDS should pass them. +# Turn them on below. +WARN_FLAGS = \ + -Wshadow \ + -Wsign-conversion \ + -pedantic -Wall -Wextra \ + -Wcast-align -Wcast-qual \ + -Wctor-dtor-privacy \ + -Wdisabled-optimization \ + -Winit-self \ + -Wmissing-declarations \ + -Wmissing-include-dirs \ + -Wcomment \ + -Wold-style-cast \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wsign-promo \ + -Wstrict-overflow=1 \ + -Wswitch-default -Wundef \ + -Werror \ + -Wno-unused \ + -Wno-unknown-pragmas \ + -Wno-long-long \ + -Wno-format + +# Here you can turn on warnings. +# CC_FULL_FLAGS = $(CC_FLAGS) +CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) -D__WASM__ + +DLLBASE = dds +STATIC_LIB = lib$(DLLBASE).a + +COMMON_SOURCE_FILES = \ + hands.cpp + +ALL_EXAMPLE_FILES = \ + AnalysePlayBin.js \ + AnalysePlayPBN \ + AnalyseAllPlaysBin \ + AnalyseAllPlaysPBN \ + CalcDDtable.cpp \ + CalcDDtablePBN.cpp \ + CalcAllTables.cpp \ + CalcAllTablesPBN.cpp \ + DealerPar.cpp \ + Par.cpp \ + SolveBoard.cpp \ + SolveBoardPBN.cpp \ + SolveAllBoards.cpp + +LIB_FLAGS = -L. $(STATIC_LIB) + +OBJ_FILES = $(subst .cpp,.o,$(COMMON_SOURCE_FILES)) +EX_OBJ_FILES = $(subst .cpp,.o,$(ALL_EXAMPLE_FILES)) +EX_EXE_FILES = $(subst .cpp,,$(ALL_EXAMPLE_FILES)) + +AnalysePlayBin.html: $(OBJ_FILES) AnalysePlayBin.cpp $(STATIC_LIB) + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) AnalysePlayBin.cpp -o AnalysePlayBin.html + +AnalysePlayPBN: $(OBJ_FILES) AnalysePlayPBN.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) AnalysePlayPBN.o -o AnalysePlayPBN + +AnalyseAllPlaysBin: $(OBJ_FILES) AnalyseAllPlaysBin.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) AnalyseAllPlaysBin.o -o AnalyseAllPlaysBin + +AnalyseAllPlaysPBN: $(OBJ_FILES) AnalyseAllPlaysPBN.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) AnalyseAllPlaysPBN.o -o AnalyseAllPlaysPBN + +CalcDDtable: $(OBJ_FILES) CalcDDtable.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) CalcDDtable.o -o CalcDDtable + +CalcDDtablePBN: $(OBJ_FILES) CalcDDtablePBN.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) CalcDDtablePBN.o -o CalcDDtablePBN + +CalcAllTables: $(OBJ_FILES) CalcAllTables.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) CalcAllTables.o -o CalcAllTables + +CalcAllTablesPBN: $(OBJ_FILES) CalcAllTablesPBN.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) CalcAllTablesPBN.o -o CalcAllTablesPBN + +DealerPar: $(OBJ_FILES) DealerPar.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) DealerPar.o -o DealerPar + +Par: $(OBJ_FILES) Par.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) Par.o -o Par + +SolveBoard: $(OBJ_FILES) SolveBoard.cpp $(STATIC_LIB) + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) SolveBoard.cpp -o SolveBoard.html + +dds: $(OBJ_FILES) dds.cpp $(STATIC_LIB) + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) dds.cpp -o dds.html + +SolveBoardPBN: $(OBJ_FILES) SolveBoardPBN.o + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) SolveBoardPBN.o -o SolveBoardPBN.html + +SolveAllBoards: $(OBJ_FILES) SolveAllBoards.cpp $(STATIC_LIB) + $(CC) $(CC_FULL_FLAGS) $(LD_FLAGS) $(LIB_FLAGS) $(OBJ_FILES) SolveAllBoards.cpp -o SolveAllBoards.html + +%.o: %.cpp + $(CC) $(CC_FULL_FLAGS) -c $< -o $*.o + +depend: + makedepend -Y -- $(cOMMON_SOURCE_FILES) $(ALL_EXAMPLE_FILES) + +clean: + rm -f *.o $(EX_EXE_FILES) $(STATIC_LIB) + diff --git a/examples/SolveBoard.cpp b/examples/SolveBoard.cpp index 61771c26..ecc62d22 100644 --- a/examples/SolveBoard.cpp +++ b/examples/SolveBoard.cpp @@ -33,7 +33,7 @@ int main() bool match2; bool match3; -#if defined(__linux) || defined(__APPLE__) +#if defined(__linux) || defined(__APPLE__) || defined(__WASM__) SetMaxThreads(0); #endif diff --git a/examples/SolveBoardPBN.cpp b/examples/SolveBoardPBN.cpp index 28c24a20..8b5e370d 100644 --- a/examples/SolveBoardPBN.cpp +++ b/examples/SolveBoardPBN.cpp @@ -33,7 +33,7 @@ int main() bool match2, match3; -#if defined(__linux) || defined(__APPLE__) +#if defined(__linux) || defined(__APPLE__) || defined(__WASM__) SetMaxThreads(0); #endif diff --git a/examples/dds.cpp b/examples/dds.cpp new file mode 100644 index 00000000..4e2fb550 --- /dev/null +++ b/examples/dds.cpp @@ -0,0 +1,148 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2016 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +/* + +S "N:QJ6.K652.J85.T98 873.J97.AT764.Q4 K5.T83.KQ9.A7652 AT942.AQ4.32.KJ3" xxxxxx +U "E:QJT5432.T.6.QJ82 .J97543.K7532.94 87.A62.QJT4.AT75 AK96.KQ8.A98.K63" xxxxxx +S "N:73.QJT.AQ54.T752 QT6.876.KJ9.AQ84 5.A95432.7632.K6 AKJ9842.K.T8.J93" xxxxxx + +*/ +// Test program for the SolveBoard function. +// Uses the hands pre-set in hands.cpp. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "../include/dll.h" +#include "../src/PBN.h" +#include "hands.h" + +/* +unsigned char dcardRank[16] = +{ + 'x', 'x', '2', '3', '4', '5', '6', '7', + '8', '9', 'T', 'J', 'Q', 'K', 'A', '-' +}; + +unsigned char dcardSuit[5] = { 'S', 'H', 'D', 'C', 'N' }; +unsigned char dcardHand[4] = { 'N', 'E', 'S', 'W' }; +*/ +int convert_trump_or_seat(char tmpChar) +{ + int rank = tmpChar - '0'; + if (rank < 15 && rank > 1) + return rank; + if (tmpChar == 'N') // North + return 0; + else if (tmpChar == 'E') + return 1; + else if (tmpChar == 'S') + return 2; + else if (tmpChar == 'W') + return 3; + else if (tmpChar == 'C') + return 3; + else if (tmpChar == 'D') + return 2; + else if (tmpChar == 'H') + return 1; + else if (tmpChar == 'S') + return 0; + else if (tmpChar == 'U') // Trump + return 4; + else if (tmpChar == 'x') // + return 0; + else if (tmpChar == 'A') // + return 14; + else if (tmpChar == 'K') // + return 13; + else if (tmpChar == 'Q') // + return 12; + else if (tmpChar == 'J') // + return 11; + else if (tmpChar == 'T') // + return 10; + else + return -1; +} + +/* + DDS, a bridge double dummy solver solveBoardPBN cli interface. + trump: 0-4 Clubs, Diamonds, Hearts, Spades, No Trump + currentTrickSuit: CDHS, AKQJT98765432 +*/ +int main(int argc, char *argv[]) +{ + if (argc < 4) { + dealPBN dlPBN; + printf("Usage: %s <board> argc=%d trump first[NESW]:dot_space_pbn currentTricks\n", argv[0], argc); + return 1; + } + + deal dl; + futureTricks fut2, // solutions == 2 + fut3; // solutions == 3 + + int target; + int solutions; + int mode; + int threadIndex = 0; + int res; + char line[80]; + bool match2; + bool match3; + +#if defined(__linux) || defined(__APPLE__) || defined(__WASM__) + SetMaxThreads(0); +#endif + + for (int handno = 0; handno < 1; handno++) + { + dl.trump = convert_trump_or_seat(argv[1][0]); + dl.first = convert_trump_or_seat(argv[2][0]); + // xxxxxx means 0,0,0,0,0,0 + dl.currentTrickSuit[0] = convert_trump_or_seat(argv[3][0]); + dl.currentTrickSuit[1] = convert_trump_or_seat(argv[3][2]); + dl.currentTrickSuit[2] = convert_trump_or_seat(argv[3][4]); + + dl.currentTrickRank[0] = convert_trump_or_seat(argv[3][1]); + dl.currentTrickRank[1] = convert_trump_or_seat(argv[3][3]); + dl.currentTrickRank[2] = convert_trump_or_seat(argv[3][5]); + + if (ConvertFromPBN(argv[2], dl.remainCards) != RETURN_NO_FAULT) { + return RETURN_PBN_FAULT; + } + + + target = -1; + mode = 0; + solutions = 2; + res = SolveBoard(dl, target, solutions, mode, &fut2, threadIndex); + if (res != RETURN_NO_FAULT) + { + ErrorMessage(res, line); + printf("DDS error: %s\n", line); + } + /* + sprintf(line, + "SolveBoard, hand %d: solutions 3 %s, solutions 2 %s\n", + handno + 1, + (match3 ? "OK" : "ERROR"), + (match2 ? "OK" : "ERROR")); + + PrintHand(line, dl.remainCards); + + sprintf(line, "solutions == 3\n"); + PrintFut(line, &fut3); + sprintf(line, "solutions == 2\n"); + */ + PrintFut(line, &fut2); + } +} diff --git a/src/Init.cpp b/src/Init.cpp index e5f85239..ab4b2ef1 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -121,6 +121,7 @@ void STDCALL SetResources( else thrMax = min(maxThreadsIn, ncores); + // printf("%d threads, %d MB memory\n", thrMax, memMaxMB); // For simplicity we won't vary the amount of memory per thread // in the small and large versions. diff --git a/src/Makefiles/Makefile_wasm b/src/Makefiles/Makefile_wasm new file mode 100644 index 00000000..d40dc339 --- /dev/null +++ b/src/Makefiles/Makefile_wasm @@ -0,0 +1,115 @@ +# --------------------- INFORMATION -------------------------------- + +# This the DDS Makefile for MacOS and the clang compiler. +# It creates a statically linked library, libdds.a. + +# --------------------- CONFIGURATION ------------------------------ + +# You can configure the following: + +# 1. The threading systems that you want in the library. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD and WINAPI don't work on Windows. +THR_BOOST = -DDDS_THREADS_BOOST +THR_GCD = -DDDS_THREADS_GCD +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_STL = -DDDS_THREADS_STL + +# THREADING = $(THR_BOOST) $(THR_GCD) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +CC_BOOST = /usr/local/Cellar/boost/1.56.0 +CC_BOOST_INCL = $(CC_BOOST)/include +CC_BOOST_LINK = -L$(CC_BOOST)/lib -lboost_system -lboost_thread-mt + +THREAD_COMPILE = +#THREAD_LINK = $(CC_BOOST_LINK) + +# 2. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER + +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt + +# If your compiler name is not given here, change it. +CC = em++ +AR = emar + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... + +WARN_FLAGS = \ + -Wshadow \ + -Wsign-conversion \ + -pedantic -Wall -Wextra \ + -Wcast-align -Wcast-qual \ + -Wctor-dtor-privacy \ + -Wdisabled-optimization \ + -Winit-self \ + -Wmissing-declarations \ + -Wmissing-include-dirs \ + -Wcomment \ + -Wold-style-cast \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wsign-promo \ + -Wstrict-overflow=1 \ + -Wswitch-default -Wundef \ + -Werror \ + -Wno-unused \ + -Wno-unknown-pragmas \ + -Wno-long-long \ + -Wno-format + +COMPILE_FLAGS = -O3 -flto -mtune=generic -std=c++11 \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) -D__WASM__ + +DLLBASE = dds +STATIC_LIB = lib$(DLLBASE).a + +include $(INCL_SOURCE) + +O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) + +$(STATIC_LIB): $(O_FILES) + $(AR) rcs $(STATIC_LIB) $(O_FILES) + +%.o: %.cpp + $(CC) $(COMPILE_FLAGS) -c $< + +depend: + makedepend -Y -- $(SOURCE_FILES) + +clean: + rm -f $(O_FILES) $(STATIC_LIB) + +install: + test -d ../test || mkdir ../test + test -d ../examples || mkdir ../examples + cp $(STATIC_LIB) ../test + cp $(STATIC_LIB) ../examples + +include $(INCL_DEPENDS) + diff --git a/src/Par.cpp b/src/Par.cpp index 89dbe032..277a6a2a 100644 --- a/src/Par.cpp +++ b/src/Par.cpp @@ -7,7 +7,7 @@ See LICENSE and README. */ - +#include <stdio.h> #include <stdexcept> #include <algorithm> #include <string.h> diff --git a/src/System.cpp b/src/System.cpp index f71f8262..4a2bfcc4 100644 --- a/src/System.cpp +++ b/src/System.cpp @@ -33,7 +33,8 @@ const vector<string> DDS_SYSTEM_PLATFORM = "Windows", "Cygwin", "Linux", - "Apple" + "Apple", + "Wasm" }; const vector<string> DDS_SYSTEM_COMPILER = @@ -42,7 +43,8 @@ const vector<string> DDS_SYSTEM_COMPILER = "Microsoft Visual C++", "MinGW", "GNU g++", - "clang" + "clang", + "em++" }; const vector<string> DDS_SYSTEM_CONSTRUCTOR = @@ -234,6 +236,13 @@ void System::GetHardware( ncores = sysconf(_SC_NPROCESSORS_ONLN); return; #endif + +#ifdef __WASM__ + // TODO find out how much memory is available + kilobytesFree = 100 * 1024; // guess 100MB + ncores = 1; + return; +#endif }