diff options
| author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2022-04-23 20:30:36 -0700 | 
|---|---|---|
| committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2022-04-23 20:31:15 -0700 | 
| commit | 2cd3bddfa34929411737ebae1f2e99fcb0cb25e2 (patch) | |
| tree | a6fde63a357537e7976122b415d700cddf0099d3 | |
| parent | c345340c022fce046d70ca67059c2b4dc648bc1e (diff) | |
| download | dartboat-2cd3bddfa34929411737ebae1f2e99fcb0cb25e2.tar.gz dartboat-2cd3bddfa34929411737ebae1f2e99fcb0cb25e2.tar.xz | |
web: support two-player scoreboard mode
| -rw-r--r-- | web/dartboat_wasm.c | 109 | ||||
| -rw-r--r-- | web/static/dartboat.js | 18 | ||||
| -rw-r--r-- | web/static/style.css | 5 | 
3 files changed, 96 insertions, 36 deletions
| diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c index 9c838bd..ccde71a 100644 --- a/web/dartboat_wasm.c +++ b/web/dartboat_wasm.c @@ -8,28 +8,39 @@  #include <emscripten/emscripten.h> -#define P_USER 1 -#define P_BOAT 2 +#define M_PVC 1 +#define M_PVP 2  int delay_ms = 1000;  // TODO refactor *everything*  struct match_state { -	struct leg *l1, *l2; +	int mode; +	struct leg *l1, *l2, *active_l; +	int active_p;  	int undone_count;  	int complete;  };  struct match_state *state; +void switch_active_user() { +	state->active_p = 3 - state->active_p; +	if (state->active_p == 1) +		state->active_l = state->l1; +	else +		state->active_l = state->l2; +	EM_ASM({setPlayerActive($0)}, state->active_p); +} +  void set_user_active() { -	EM_ASM({setPlayerActive($0)}, P_USER); +	EM_ASM({setPlayerActive($0)}, 1);  	EM_ASM({setPromptHandler($0)}, "visit");  }  void set_boat_active() { -	EM_ASM({setPlayerActive($0)}, P_BOAT); +	EM_ASM({setPlayerActive($0)}, 2);  	EM_ASM({setPromptHandler()}, "");  } @@ -69,7 +80,8 @@ EMSCRIPTEN_KEEPALIVE int is_match_over() {  void match_over() {  	EM_ASM({setPromptHandler($0)}, "init"); -	EM_ASM({promptMsgR($0)}, "Press OK to play again."); +	EM_ASM({promptMsgL($0)}, "Enter match mode:"); +	EM_ASM({promptMsgR($0)}, "1 to play against bot\n2 to play against player");  	EM_ASM(setPlayerActive());  } @@ -118,8 +130,13 @@ EMSCRIPTEN_KEEPALIVE void draw_match() {  		EM_ASM({promptMsgL($0)}, "Darts needed?");  		EM_ASM({setPromptHandler($0)}, "num_darts");  	} else if (l2->rem <= 0) { -		EM_ASM({promptMsgL($0)}, "Bot wins. :("); -		match_over(); +		if (state->mode == M_PVC) { +			EM_ASM({promptMsgL($0)}, "Bot wins. :("); +			match_over(); +		} else { +			EM_ASM({promptMsgL($0)}, "Darts needed?"); +			EM_ASM({setPromptHandler($0)}, "num_darts"); +		}  	} else {  		EM_ASM({promptMsgL($0)}, "Enter points:");  	} @@ -138,22 +155,22 @@ char *str_for_rem_state(int rem) {  EMSCRIPTEN_KEEPALIVE void update_user_rem(int rem) {  	char *str = str_for_rem_state(rem); -	EM_ASM({updatePlayerRem($0, $1)}, P_USER, str); +	EM_ASM({updatePlayerRem($0, $1)}, state->active_p, str);  	free(str); -	get_suggested(rem, P_USER); +	get_suggested(rem, state->active_p);  }  EMSCRIPTEN_KEEPALIVE void update_user_rem_from_pts(int pts) { -	update_user_rem(state->l1->rem - pts); +	update_user_rem(state->active_l->rem - pts);  }  EMSCRIPTEN_KEEPALIVE void update_boat_rem(int rem) {  	char *str = str_for_rem_state(rem); -	EM_ASM({updatePlayerRem($0, $1)}, P_BOAT, str); +	EM_ASM({updatePlayerRem($0, $1)}, 2, str);  	free(str); -	get_suggested(rem, P_BOAT); +	get_suggested(rem, 2);  }  void end_boat_throwing(int, double); // FIXME @@ -206,7 +223,7 @@ EMSCRIPTEN_KEEPALIVE void boat_visit() {  EMSCRIPTEN_KEEPALIVE bool user_visit(int points) {  	if (state->l1->rem <= 0 || state->l2->rem <= 0 || -		points > state->l1->rem || state->l1->rem - points == 1 || +		points > state->active_l->rem || state->active_l->rem - points == 1 ||  		points > 180 || points == 179 || points == 178 || points == 176 ||  		points == 175 || points == 173 || points == 172 || points == 169 ||  		points == 166 || points == 163) { @@ -215,7 +232,7 @@ EMSCRIPTEN_KEEPALIVE bool user_visit(int points) {  		return false;  	} -	struct leg *l = state->l1; +	struct leg *l = state->active_l;  	struct visit *v = l->visits + l->n_visits++;  	v->points = points;  	l->rem -= points; @@ -223,15 +240,19 @@ EMSCRIPTEN_KEEPALIVE bool user_visit(int points) {  	update_user_rem(l->rem);  	if (v->rem > 0) -		EM_ASM({updatePlayerAvg($0, $1)}, P_USER, +		EM_ASM({updatePlayerAvg($0, $1)}, state->active_p,  			(double)(l->start-l->rem)/l->n_visits);  	EM_ASM({clearVisits()});  	draw_match();  	if (!is_match_over()) { -		set_boat_active(); -		boat_visit(); +		if (state->mode == M_PVC) { +			set_boat_active(); +			boat_visit(); +		} else { +			switch_active_user(); +		}  	}  	return true; @@ -248,19 +269,25 @@ EMSCRIPTEN_KEEPALIVE bool user_undo() {  		return false;  	} -	struct leg *l = state->l1; +	if (state->mode == M_PVP) +		switch_active_user(); + +	struct leg *l = state->active_l;  	struct visit *v = l->visits + --l->n_visits;  	l->rem += v->points; -	state->l2->rem += state->l2->visits[--state->l2->n_visits].points; -	++state->undone_count; +	if (state->mode == M_PVC) { +		state->l2->rem += state->l2->visits[--state->l2->n_visits].points; +		++state->undone_count; +	} -	EM_ASM({updatePlayerAvg($0, $1)}, P_USER, +	EM_ASM({updatePlayerAvg($0, $1)}, 1,  		l->n_visits ? (double)(l->start-l->rem)/l->n_visits : 0); -	EM_ASM({updatePlayerAvg($0, $1)}, P_BOAT, +	EM_ASM({updatePlayerAvg($0, $1)}, 2,  		state->l2->n_visits ?  			(double)(state->l2->start-state->l2->rem)/state->l2->n_visits : 0);  	update_user_rem(l->rem); -	update_boat_rem(state->l2->rem); +	if (state->mode == M_PVC) +		update_boat_rem(state->l2->rem);  	memcpy(v, 0, sizeof(*v)); @@ -284,7 +311,7 @@ EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str) {  EMSCRIPTEN_KEEPALIVE void end_boat_throwing(int rem, double avg) {  	update_boat_rem(rem); -	EM_ASM({updatePlayerAvg($0, $1)}, P_BOAT, avg); +	EM_ASM({updatePlayerAvg($0, $1)}, 2, avg);  	EM_ASM({setPromptInput($0)}, "");  	EM_ASM(clearVisits());  	EM_ASM({promptMsgR($0)}, ""); @@ -302,7 +329,7 @@ EMSCRIPTEN_KEEPALIVE void resp_numdarts(int n_darts) {  	struct leg *l = state->l1; -	EM_ASM({updatePlayerAvg($0, $1)}, P_USER, +	EM_ASM({updatePlayerAvg($0, $1)}, state->active_p,  		((double)l->start / (((l->n_visits - 1) * 3) + n_darts)) * 3);  	EM_ASM({promptMsgL($0)}, "You win! :)");  	match_over(); @@ -330,20 +357,33 @@ EMSCRIPTEN_KEEPALIVE void free_match() {  	state = NULL;  } -EMSCRIPTEN_KEEPALIVE void start_match() { +EMSCRIPTEN_KEEPALIVE void start_match(int mode) { +	if (mode != M_PVP && mode != M_PVC) { +		EM_ASM(oi()); +		return; +	} +  	if (state) free_match();  	init_boat();  	state = calloc(1, sizeof(*state)); -	state->l1 = leg_init(501, "User"); -	state->l2 = leg_init(501, "Bot"); +	state->mode = mode; +	if (mode == M_PVC) { +		state->l1 = leg_init(501, "User"); +		state->l2 = leg_init(501, "Bot"); +	} else { +		state->l1 = leg_init(501, "Player 1"); +		state->l2 = leg_init(501, "Player 2"); +	} +	state->active_p = 1; +	state->active_l = state->l1; -	EM_ASM({updatePlayerName($0, $1)}, P_USER, state->l1->name); -	EM_ASM({updatePlayerName($0, $1)}, P_BOAT, state->l2->name); +	EM_ASM({updatePlayerName($0, $1)}, 1, state->l1->name); +	EM_ASM({updatePlayerName($0, $1)}, 2, state->l2->name);  	update_user_rem(state->l1->rem);  	update_boat_rem(state->l2->rem); -	EM_ASM({updatePlayerAvg($0, $1)}, P_USER, 0); -	EM_ASM({updatePlayerAvg($0, $1)}, P_BOAT, 0); +	EM_ASM({updatePlayerAvg($0, $1)}, 1, 0); +	EM_ASM({updatePlayerAvg($0, $1)}, 2, 0);  	EM_ASM(clearVisits());  	set_user_active(); @@ -362,5 +402,6 @@ EMSCRIPTEN_KEEPALIVE void set_delay(int delay) {  int main() {  	EM_ASM(read_opts()); -	start_match(); +	init_boat(); +	match_over();  } diff --git a/web/static/dartboat.js b/web/static/dartboat.js index 6740381..7324ad0 100644 --- a/web/static/dartboat.js +++ b/web/static/dartboat.js @@ -125,8 +125,24 @@ let prompt_handlers = {  	},  	init: { +		append(val) { +			let e = document.getElementById('prompt-input'); +			if (e.textContent.length < 1) +				e.textContent += val; +		}, + +		backspace() { +			_promptDeleteLast(); +		}, + +		clear() { +			_promptClear(); +		}, +  		submit() { -			Module.ccall('start_match'); +			let v = _promptGetAndClear(); +			if (v) +				Module.ccall('start_match', null, ['number'], [v]);  		},  		pre(action) { diff --git a/web/static/style.css b/web/static/style.css index 397d5f8..8da0cbc 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -32,7 +32,7 @@ div#keypad {  	display: grid;  	grid-template-columns: repeat(3, 1fr); -	grid-template-rows: 1.2fr; +	grid-template-rows: minmax(5em, auto);  	grid-auto-rows: 1fr;  } @@ -98,6 +98,8 @@ div#p1-sugg, div#p2-sugg {  	font-size: 0.8em;  } +div#p1-name:after, div#p2-name:after, +div#p1-rem:after, div#p2-rem:after,  div#p1-sugg:after, div#p2-sugg:after {  	content: '\200b';  } @@ -126,6 +128,7 @@ div#prompt-container {  div#prompt-msg-l, div#prompt-input, div#prompt-msg-r {  	font-size: 1.5em; +	white-space: pre-line;  	display: grid;  	align-items: center; | 
