diff options
| -rw-r--r-- | web/dartboat_wasm.c | 214 | ||||
| -rw-r--r-- | web/static/dartboat.js | 4 | ||||
| -rw-r--r-- | web/static/index.html | 2 | ||||
| -rw-r--r-- | web/static/style.css | 2 | 
4 files changed, 117 insertions, 105 deletions
| diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c index 6580716..b44a9b8 100644 --- a/web/dartboat_wasm.c +++ b/web/dartboat_wasm.c @@ -11,30 +11,31 @@  int delay_ms = 500;  enum match_mode { -	M_PVC = 1, +	M_FIRST = 1, +	M_PVC = M_FIRST,  	M_P, -	M_PVP +	M_PVP, +	M_LAST = M_PVP  }; -// TODO refactor *everything* -  struct match_state {  	enum match_mode mode; -	struct leg *l1, *l2, *active_l; -	int active_p; -	int undone_count; +	struct leg *legs[2]; +	struct leg *active_leg; +	int active_player; +	int boat_undone;  	bool num_darts;  };  struct match_state *state; -void set_active_player(int player) +void set_active_player(int pn)  { -	state->active_p = player; -	state->active_l = player == 1 ? state->l1 : state->l2; -	EM_ASM({setPlayerActive($0)}, player); +	state->active_player = pn; +	state->active_leg = state->legs[pn-1]; +	EM_ASM({setPlayerActive($0)}, pn); -	if (state->mode == M_PVC && player == 2) { +	if (state->mode == M_PVC && pn == 2) {  		EM_ASM({promptMsgL($0)}, "Bot is throwing…");  		EM_ASM({setPromptHandler($0)}, "");  	} else { @@ -46,10 +47,10 @@ void set_active_player(int player)  void toggle_active_player()  { -	set_active_player(3 - state->active_p); +	set_active_player(3 - state->active_player);  } -void update_player_sugg(int player, int rem) +void update_player_sugg(int pn, int rem)  {  	char str[15] = {0}, *p = str; @@ -62,19 +63,12 @@ void update_player_sugg(int player, int rem)  		}  	} -	EM_ASM({updatePlayerSugg($0, $1)}, player, str); +	EM_ASM({updatePlayerSugg($0, $1)}, pn, str);  }  bool is_match_over()  { -	return state->l1->rem <= 0 || state->l2->rem <= 0; -} - -void prompt_end_match() -{ -	EM_ASM(setPlayerActive()); // sets all inactive -	EM_ASM({setPromptHandler($0)}, "end_match"); -	EM_ASM({promptMsgR($0)}, "Press OK to end match."); +	return state->legs[0]->rem <= 0 || state->legs[1]->rem <= 0;  }  void draw_visits() @@ -84,25 +78,25 @@ void draw_visits()  	char visit_no[10], p1_pts[10], p1_rem[10],  		p2_pts[10], p2_rem[10], p2_darts[100]; -	sprintf(p1_rem, "%d", state->l1->start); -	sprintf(p2_rem, "%d", state->l2->start); +	sprintf(p1_rem, "%d", state->legs[0]->start); +	sprintf(p2_rem, "%d", state->legs[1]->start);  	EM_ASM({drawVisit($0, $1, $2, $3, $4, $5)},  		"0", "", p1_rem, "", state->mode == M_P ? "" : p2_rem, ""); -	int n_visits = state->l1->n_visits > state->l2->n_visits ? -		state->l1->n_visits : state->l2->n_visits; +	int n_visits = state->legs[0]->n_visits > state->legs[1]->n_visits ? +		state->legs[0]->n_visits : state->legs[1]->n_visits;  	for (int i = 0; i < n_visits; ++i) {  		visit_no[0] = p1_pts[0] = p1_rem[0] =  			p2_pts[0] = p2_rem[0] = p2_darts[0] = 0;  		sprintf(visit_no, "%d", i + 1); -		struct visit *v = state->l1->visits + i; +		struct visit *v = state->legs[0]->visits + i;  		sprintf(p1_pts, "%d", v->points);  		sprintf(p1_rem, "%d", v->rem); -		if (i < state->l2->n_visits) { -			v = state->l2->visits + i; +		if (i < state->legs[1]->n_visits) { +			v = state->legs[1]->visits + i;  			sprintf(p2_pts, "%d", v->points);  			sprintf(p2_rem, "%d", v->rem); @@ -119,7 +113,7 @@ void draw_visits()  	}  } -void update_player_rem(int player, int rem) +void update_player_rem(int pn, int rem)  {  	char str[5];  	if (rem < 0 || rem == 1) @@ -127,14 +121,14 @@ void update_player_rem(int player, int rem)  	else  		sprintf(str, "%d", rem); -	EM_ASM({updatePlayerRem($0, $1)}, player, str); -	if (player == 1 || state->mode != M_PVC) -		update_player_sugg(player, rem); +	EM_ASM({updatePlayerRem($0, $1)}, pn, str); +	if (pn == 1 || state->mode != M_PVC) +		update_player_sugg(pn, rem);  }  EMSCRIPTEN_KEEPALIVE void update_user_rem_from_pts(int pts)  { -	update_player_rem(state->active_p, state->active_l->rem - pts); +	update_player_rem(state->active_player, state->active_leg->rem - pts);  }  EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str) @@ -142,8 +136,9 @@ EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str)  	char pts_str[10];  	sprintf(pts_str, "%d", pts); -	int rem = state->l2->n_visits > 1 ? -		state->l2->visits[state->l2->n_visits-2].rem : state->l2->start; +	int rem = state->legs[1]->n_visits > 1 ? +		state->legs[1]->visits[state->legs[1]->n_visits-2].rem : +		state->legs[1]->start;  	update_player_rem(2, rem - pts);  	EM_ASM({setPromptInput($0)}, pts_str); @@ -151,7 +146,7 @@ EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str)  }  void handle_next(); -EMSCRIPTEN_KEEPALIVE void end_boat_throwing(int rem, double avg) +EMSCRIPTEN_KEEPALIVE void end_boat_visit(int rem, double avg)  {  	update_player_rem(2, rem);  	EM_ASM({updatePlayerAvg($0, $1)}, 2, avg); @@ -164,9 +159,9 @@ EMSCRIPTEN_KEEPALIVE void end_boat_throwing(int rem, double avg)  EMSCRIPTEN_KEEPALIVE void boat_visit()  { -	struct leg *l = state->l2; -	if (state->undone_count) { -		--state->undone_count; +	struct leg *l = state->legs[1]; +	if (state->boat_undone) { +		--state->boat_undone;  		l->rem = l->visits[l->n_visits++].rem;  	} else {  		comp_visit(l); @@ -178,7 +173,7 @@ EMSCRIPTEN_KEEPALIVE void boat_visit()  		(double)l->start / (((l->n_visits - 1) * 3) + v->n_darts) * 3;  	if (!delay_ms) { -		end_boat_throwing(l->rem, avg); +		end_boat_visit(l->rem, avg);  		return;  	} @@ -197,7 +192,7 @@ EMSCRIPTEN_KEEPALIVE void boat_visit()  	}  	EM_ASM({scheduleCCall($0, $1, $2, $3, $4, $5)}, -		"end_boat_throwing", delay_ms * (v->n_darts + 1), +		"end_boat_visit", delay_ms * (v->n_darts + 1),  		"number", l->rem, "number", avg);  } @@ -209,7 +204,24 @@ void clear_player_info(int pn)  	EM_ASM({updatePlayerAvg($0, $1)}, pn, 0);  } -EMSCRIPTEN_KEEPALIVE void prompt_match_mode() +void prompt_num_darts() +{ +	EM_ASM({setPromptHandler($0)}, "num_darts"); +	EM_ASM({promptMsgL($0)}, "Darts needed?"); +	EM_ASM({promptMsgR($0)}, ""); +} + +void prompt_end_match() +{ +	EM_ASM(setPlayerActive()); // sets all inactive +	EM_ASM({setPromptHandler($0)}, "end_match"); +	EM_ASM({promptMsgL($0)}, +		state->mode == M_PVC && state->legs[1]->rem <= 0 ? "Bot wins. :(" : +			"You win! :)"); +	EM_ASM({promptMsgR($0)}, "Press OK to end match."); +} + +EMSCRIPTEN_KEEPALIVE void prompt_select_mode()  {  	for (int pn = 1; pn < 3; ++pn) {  		EM_ASM({hidePlayerInfo($0)}, pn); @@ -217,62 +229,69 @@ EMSCRIPTEN_KEEPALIVE void prompt_match_mode()  	}  	EM_ASM(clearVisits()); -	EM_ASM({setPromptHandler($0)}, "match_mode"); -	EM_ASM({promptMsgR($0)}, ""); +	EM_ASM({setPromptHandler($0)}, "select_mode");  	EM_ASM({promptMsgL($0)}, "Select match mode:"); +	EM_ASM({promptMsgR($0)}, "");  }  void handle_next()  {  	if (!state) { -		prompt_match_mode(); +		prompt_select_mode();  	} else if (is_match_over()) { -		if (state->mode == M_PVC && state->l2->rem <= 0) { -			EM_ASM({promptMsgL($0)}, "Bot wins. :("); +		if (state->num_darts || +			(state->mode == M_PVC && state->legs[1]->rem <= 0))  			prompt_end_match(); -		} else if (!state->num_darts) { -			EM_ASM({setPromptHandler($0)}, "num_darts"); -			EM_ASM({promptMsgL($0)}, "Darts needed?"); -		} else { -			EM_ASM({promptMsgL($0)}, "You win! :)"); -			prompt_end_match(); -		} +		else +			prompt_num_darts();  	} else {  		if (state->mode == M_P) {  			set_active_player(1);  		} else { -			toggle_active_player(); +			if (state->active_player) +				toggle_active_player(); +			else +				set_active_player(1); -			if (state->mode == M_PVC && state->active_p == 2) +			if (state->mode == M_PVC && state->active_player == 2)  				boat_visit();  		}  	}  } +void update_player_avg(int pn, int n_darts) +{ +	struct leg *l = state->legs[pn-1]; +	EM_ASM({updatePlayerAvg($0, $1)}, pn, +		l->n_visits ? +			(l->rem > 0 ? ((double)(l->start - l->rem) / l->n_visits) : +				((double)l->start / (((l->n_visits - 1) * 3) + n_darts) * 3)) : +			0); +} +  EMSCRIPTEN_KEEPALIVE void user_visit(int points)  { -	if (points < 0 || state->l1->rem <= 0 || state->l2->rem <= 0 || -		points > state->active_l->rem || state->active_l->rem - points == 1 || +	if (points < 0 || points > state->active_leg->rem || +		state->active_leg->rem - points == 1 ||  		points > 180 || points == 179 || points == 178 || points == 176 ||  		points == 175 || points == 173 || points == 172 || points == 169 ||  		points == 166 || points == 163 || -		(state->active_l->rem - points == 0 && -			(points == 168 || points == 165 || points == 162 || points == 159))) { - +		(state->active_leg->rem - points == 0 && +			(points == 168 || points == 165 || points == 162 || +				points == 159))) {  		EM_ASM(oi());  		return;  	} -	struct leg *l = state->active_l; +	struct leg *l = state->active_leg;  	struct visit *v = l->visits + l->n_visits++;  	v->points = points;  	l->rem -= points;  	v->rem = l->rem; -	update_player_rem(state->active_p, l->rem); +	update_player_rem(state->active_player, l->rem);  	if (v->rem > 0) -		EM_ASM({updatePlayerAvg($0, $1)}, state->active_p, -			(double)(l->start-l->rem)/l->n_visits); +		update_player_avg(state->active_player, 0);  	draw_visits();  	handle_next(); @@ -280,12 +299,12 @@ EMSCRIPTEN_KEEPALIVE void user_visit(int points)  EMSCRIPTEN_KEEPALIVE void user_visit_to_rem(int rem)  { -	user_visit(state->l1->rem - rem); +	user_visit(state->legs[0]->rem - rem);  }  EMSCRIPTEN_KEEPALIVE void user_undo()  { -	if (!state->l1->n_visits) { +	if (!state->legs[0]->n_visits) {  		EM_ASM(oi());  		return;  	} @@ -294,33 +313,29 @@ EMSCRIPTEN_KEEPALIVE void user_undo()  		set_active_player(1);  	} else if (state->mode == M_PVP) {  		if (is_match_over()) -			set_active_player(state->active_p); +			set_active_player(state->active_player);  		else  			toggle_active_player();  	} -	struct leg *l = state->active_l; +	struct leg *l = state->active_leg;  	struct visit *v = l->visits + --l->n_visits;  	l->rem += v->points;  	memcpy(v, 0, sizeof(*v));  	state->num_darts = 0; -	if (state->mode == M_PVC && state->l2->n_visits > l->n_visits) { -		state->l2->rem += state->l2->visits[--state->l2->n_visits].points; -		++state->undone_count; +	if (state->mode == M_PVC && state->legs[1]->n_visits > l->n_visits) { +		state->legs[1]->rem += +			state->legs[1]->visits[--state->legs[1]->n_visits].points; +		++state->boat_undone;  	} -	EM_ASM({updatePlayerAvg($0, $1)}, 1, -		state->l1->n_visits ? -			(double)(state->l1->start - state->l1->rem) / state->l1->n_visits : -			0); -	EM_ASM({updatePlayerAvg($0, $1)}, 2, -		state->l2->n_visits ? -			(double)(state->l2->start - state->l2->rem) / state->l2->n_visits : -			0); -	update_player_rem(state->active_p, l->rem); -	if (state->mode == M_PVC) -		update_player_rem(2, state->l2->rem); +	update_player_avg(state->active_player, 0); +	update_player_rem(state->active_player, l->rem); +	if (state->mode == M_PVC) { +		update_player_avg(2, 0); +		update_player_rem(2, state->legs[1]->rem); +	}  	draw_visits(); @@ -337,50 +352,47 @@ EMSCRIPTEN_KEEPALIVE void user_num_darts(int n)  	}  	state->num_darts = n; - -	struct leg *l = state->active_l; -	EM_ASM({updatePlayerAvg($0, $1)}, state->active_p, -		((double)l->start / (((l->n_visits - 1) * 3) + n)) * 3); +	update_player_avg(state->active_player, n);  	handle_next();  }  void free_state()  { -	state->l2->n_visits += state->undone_count; // avoid memory leak -	leg_free(state->l1); -	leg_free(state->l2); +	state->legs[1]->n_visits += state->boat_undone; // avoid memory leak +	leg_free(state->legs[0]); +	leg_free(state->legs[1]);  	free(state);  	state = NULL;  }  EMSCRIPTEN_KEEPALIVE void start_match(int mode)  { -	if (mode != M_PVP && mode != M_PVC && mode != M_P) { +	if (mode < M_FIRST || mode > M_LAST) {  		EM_ASM(oi());  		return;  	} -	if (state) free_state(); // FIXME +	if (state) free_state(); // this should never happen  	state = calloc(1, sizeof(*state));  	state->mode = mode; -	state->l1 = leg_init(501, mode == M_PVP ? "Player 1" : "User"); -	state->l2 = leg_init(501, mode == M_PVC ? "Bot" : "Player 2"); -	set_active_player(1); +	state->legs[0] = leg_init(501, mode == M_PVP ? "Player 1" : "User"); +	state->legs[1] = leg_init(501, mode == M_PVC ? "Bot" : "Player 2");  	EM_ASM({showPlayerInfo($0)}, 1); -	EM_ASM({updatePlayerName($0, $1)}, 1, state->l1->name); -	update_player_rem(1, state->l1->rem); +	EM_ASM({updatePlayerName($0, $1)}, 1, state->legs[0]->name); +	update_player_rem(1, state->legs[0]->rem);  	EM_ASM({updatePlayerAvg($0, $1)}, 1, 0);  	if (mode != M_P) {  		EM_ASM({showPlayerInfo($0)}, 2); -		EM_ASM({updatePlayerName($0, $1)}, 2, state->l2->name); -		update_player_rem(2, state->l2->rem); +		EM_ASM({updatePlayerName($0, $1)}, 2, state->legs[1]->name); +		update_player_rem(2, state->legs[1]->rem);  		EM_ASM({updatePlayerAvg($0, $1)}, 2, 0);  	}  	draw_visits(); +	handle_next();  }  EMSCRIPTEN_KEEPALIVE void end_match() diff --git a/web/static/dartboat.js b/web/static/dartboat.js index cb8e9dd..9cedc4a 100644 --- a/web/static/dartboat.js +++ b/web/static/dartboat.js @@ -123,9 +123,9 @@ prompt_handlers.end_match = {  	}  }; -prompt_handlers.match_mode = { +prompt_handlers.select_mode = {  	__proto__: prompt_handlers.default, -	_keypad: 'match_mode', +	_keypad: 'select_mode',  	submit() {  		let v = this._get_and_clear(); diff --git a/web/static/index.html b/web/static/index.html index e1384bb..1177e40 100644 --- a/web/static/index.html +++ b/web/static/index.html @@ -47,7 +47,7 @@  					<div onclick="promptHandle('undo')" class="key" id="key_undo">UNDO</div>  					<div onclick="promptHandle('submit_rem')" class="key">REMAINING</div>  				</div> -				<div id="keypad-match_mode" class="keypad"> +				<div id="keypad-select_mode" class="keypad">  					<div onclick="promptHandle('append', 1); promptHandle('submit')" class="key"><span class="keyboard-val">[1]</span> Play against bot</div>  					<div onclick="promptHandle('append', 2); promptHandle('submit')" class="key"><span class="keyboard-val">[2]</span> One-player scoreboard</div>  					<div onclick="promptHandle('append', 3); promptHandle('submit')" class="key"><span class="keyboard-val">[3]</span> Two-player scoreboard</div> diff --git a/web/static/style.css b/web/static/style.css index 519a437..e43a0c1 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -42,7 +42,7 @@ div#controls .keypad {  	display: contents;  } -div#controls #keypad-match_mode .key { +div#controls #keypad-select_mode .key {  	grid-column: 1 / -1;  	padding-left: 0.4rem; | 
