Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build/
*.o
*.exe
17 changes: 11 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,27 @@
# Updated to link into a single executable
#

CC=gcc
CC=emcc
RM=rm -f
CFLAGS=-c -Wall -O3
LDFLAGS=-lm -mconsole
CFLAGS=-c -Wall -g -sWASM_WORKERS
LDFLAGS=-lm -mconsole --shell-file html_template/shell_minimal.html -sNO_EXIT_RUNTIME -sEXPORTED_RUNTIME_METHODS=ccall,cwrap,wasmMemory,getValue,setValue -sNO_INVOKE_RUN -sASSERTIONS -sEXPORT_ALL -g -sERROR_ON_WASM_CHANGES_AFTER_LINK -sWASM_BIGINT -sENVIRONMENT=web,webview,worker -sEXPORT_NAME="createModule" -sMODULARIZE -sWASM_WORKERS
SOURCES=$(wildcard *.c)
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=dominoai # Name your executable
EXECUTABLE=build/domino-c.html # Name your executable
EXEC_DIR=$(dir $(EXECUTABLE))

.PHONY: all clean

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
$(EXECUTABLE): $(OBJECTS) html_template/shell_minimal.html | $(EXEC_DIR)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@

%.o: %.c
$(EXEC_DIR):
# HACK: the following wont work for nested directories, i dont expect i will be doing that anytime soon since making that cross platform is a pain
mkdir $@

%.o: %.c Makefile
$(CC) $(CFLAGS) $< -o $@

clean:
Expand Down
19 changes: 19 additions & 0 deletions game.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
#include "game.h"

#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#define KEEPALIVE EMSCRIPTEN_KEEPALIVE
#else
#define KEEPALIVE
#endif

unsigned long long FACTORIAL[DCOUNT];

KEEPALIVE
void init_fact(){
FACTORIAL[0] = 1;
for(int i = 1; i < DCOUNT; i++){
Expand All @@ -10,6 +18,7 @@ void init_fact(){
}

// initialize a game
KEEPALIVE
void init_game(Game *g) {
init_blocks(g->block_set);
g->snake.head = NULL;
Expand All @@ -18,6 +27,7 @@ void init_game(Game *g) {
init_hands(&g->hands);
}

KEEPALIVE
int playable_move(Snake *s, enum Type type, int left, int right) {
if(s->head == NULL)
return 1;
Expand Down Expand Up @@ -51,6 +61,7 @@ int playable_domino(Snake *s, int left, int right) {
|| right == s->head->domino.right || right == s->tail->domino.left;
}

KEEPALIVE
int is_passing(Game *g, int player){ // test whether a player will pass if given the turn for certain
int left = g->snake.tail->domino.left;
int right = g->snake.head->domino.right;
Expand All @@ -61,6 +72,7 @@ int is_passing(Game *g, int player){ // test whether a player will pass if given
return 1;
}

KEEPALIVE
void print_game(Game *g){
printf("-------------------------------------------------------------\n");
// print the hands then the snake.
Expand All @@ -71,6 +83,7 @@ void print_game(Game *g){
printf("Pass Counter: %d\n", g->pass_counter);
}

KEEPALIVE
void get_playing_moves(Game *g, Move moves[MAX_NUM_PLY_MOVE], int *n, int *cant_pass){
*n = 0;
*cant_pass = 0;
Expand Down Expand Up @@ -112,6 +125,7 @@ void get_playing_moves(Game *g, Move moves[MAX_NUM_PLY_MOVE], int *n, int *cant_
}
}

KEEPALIVE
void get_perfect_picking_moves(Game *g, Move moves[], int *n){
*n = 0;
if(g->hands.hand_sizes[NP] == 0)
Expand All @@ -134,6 +148,7 @@ void deb(Game *g){
get_playable_perfect_picking_moves(g, perf, &n);
}

KEEPALIVE
void get_playable_perfect_picking_moves(Game *g, Move moves[], int *n){
*n = 0;
if(g->hands.hand_sizes[NP] == 0)
Expand All @@ -150,6 +165,7 @@ void get_playable_perfect_picking_moves(Game *g, Move moves[], int *n){
}
}

KEEPALIVE
float pick_unplayable_domino_probability_from_moves(Game *g, Move play_perf[], int nplayperf){
int nplaysolid = 0, nplayliquid = 0;
for(int i = 0; i < nplayperf; i++){
Expand All @@ -171,6 +187,7 @@ float pick_unplayable_domino_probability(Game *g, int n_solid, int n_liquid){ //
return liquid_prob + solid_prob;
}

KEEPALIVE
float pass_probability_from_num_moves(Game *g, int n){
if(g->snake.head == NULL)
return 0.0f;
Expand Down Expand Up @@ -253,6 +270,7 @@ void pick_liquid_update(Game *g){
unabsent(g);
}

KEEPALIVE
void pass(Game *g){
absent(g);
emit_collapse(&g->hands);
Expand Down Expand Up @@ -291,6 +309,7 @@ void undo_imperfect_pick(Game *g, Hands *prev){
g->hands = *prev;
}

KEEPALIVE
int over(Game *g){
if(g->pass_counter == NP)
return 1;
Expand Down
15 changes: 15 additions & 0 deletions hands.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#include "hands.h"

#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#define KEEPALIVE EMSCRIPTEN_KEEPALIVE
#else
#define KEEPALIVE
#endif

int calc_solid_weight(int player, Hands *hands){
int w = 0;
for(int i = 0; i < PIPS; i++){
Expand Down Expand Up @@ -148,6 +155,7 @@ void and_ownership(int value, Hands *hands, int i, int j){
hands->ownership[j][i] &= value;
}

KEEPALIVE
int possible_possession(int player, Hands *hands, int i, int j){
return hands->ownership[i][j] & (1 << player);
}
Expand All @@ -171,10 +179,12 @@ int sole_owner(Hands *hands, int i, int j){
return __builtin_ctz(hands->ownership[i][j]);
}

KEEPALIVE
int hand_is_solid(int player, Hands *hands){
return hands->solid_groups[player].size == hands->hand_sizes[player];
}

KEEPALIVE
int hand_is_liquid(int player, Hands *hands){
return hands->solid_groups[player].size == 0;
}
Expand All @@ -183,6 +193,7 @@ int hand_is_empty(int player, Hands *hands){
return hands->hand_sizes[player] == 0;
}

KEEPALIVE
int boneyard_is_pickable(Hands *hands){
#if BLOCK
return 0;
Expand All @@ -205,6 +216,7 @@ void set_sole_owner_pick(int player, Hands *hands, int i, int j){ // needs not b
set_ownership((1 << player), hands, i, j);
}

KEEPALIVE
void collapse_piece(int player, Hands *hands, int i, int j){ // collapse piece to the player
if(certain(hands, i, j) || !possible_possession(player, hands, i, j))
return;
Expand All @@ -216,6 +228,7 @@ void collapse_piece(int player, Hands *hands, int i, int j){ // collapse piece t
set_ownership((1 << player), hands, i, j);
}

KEEPALIVE
void absent_piece(int player, Hands *hands, int i, int j){ // piece is not in the player's hand
if(!possible_possession(player, hands, i, j) || certain(hands, i, j))
return;
Expand Down Expand Up @@ -317,6 +330,7 @@ int collapse_hand(int player, Hands *hands){
return 0;
}

KEEPALIVE
void emit_collapse(Hands *hands){
for(int p = 0; p <= NP; p++){
cascade_collapse(p, hands);
Expand Down Expand Up @@ -366,6 +380,7 @@ void print_hands(Hands *hands){
}
}

KEEPALIVE
void get_hand_sizes(Hands *hands) {
// TODO: allow silent games
for(int i = 0; i < NP; i++){
Expand Down
Loading