| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- #include "ttt_multi_game_view.h"
- struct TttMultiGameView {
- View* view;
- };
- typedef struct {
- TttMultiGame* game;
- uint8_t position_x;
- uint8_t position_y;
- TttMultiGamePlayer local_player;
- bool is_local;
- TttMultiGameViewCallback callback;
- void* context;
- TttMultiGameMove* last_move;
- TttMultiGameResult result;
- } TttMultiGameViewModel;
- void ttt_multi_game_view_draw_callback(Canvas* canvas, void* _model) {
- TttMultiGameViewModel* model = _model;
- canvas_clear(canvas);
- const uint8_t top = 2;
- const uint8_t left = 4;
- const uint8_t cell_size = 20;
- const uint8_t padding = 4;
- canvas_draw_frame(canvas, left - 1, top - 1, 3 * cell_size + 2, 3 * cell_size + 2);
- for(uint8_t i = 0; i < 3; i++) {
- for(uint8_t j = 0; j < 3; j++) {
- canvas_draw_frame(
- canvas, left + i * cell_size, top + j * cell_size, cell_size, cell_size);
- }
- }
- for(uint8_t i = 0; i < 3; i++) {
- for(uint8_t j = 0; j < 3; j++) {
- bool is_selected = model->position_x == i && model->position_y == j &&
- ttt_multi_game_get_state(model->game) != TttMultiGameStateFinished;
- if(ttt_multi_game_player_at(model->game, i, j) == TttMultiGamePlayerX) {
- canvas_draw_line(
- canvas,
- left + i * cell_size + padding,
- top + j * cell_size + padding,
- left + i * cell_size + cell_size - padding,
- top + j * cell_size + cell_size - padding);
- canvas_draw_line(
- canvas,
- left + i * cell_size + cell_size - padding,
- top + j * cell_size + padding,
- left + i * cell_size + padding,
- top + j * cell_size + cell_size - padding);
- } else if(ttt_multi_game_player_at(model->game, i, j) == TttMultiGamePlayerO) {
- canvas_draw_circle(
- canvas,
- left + i * cell_size + cell_size / 2,
- top + j * cell_size + cell_size / 2,
- cell_size / 2 - padding);
- }
- if(is_selected) {
- canvas_draw_frame(
- canvas,
- left + i * cell_size + 1,
- top + j * cell_size + 1,
- cell_size - 2,
- cell_size - 2);
- }
- }
- }
- char* status_str = "";
- // TODO: Rewrite this
- if(model->is_local) {
- if(ttt_multi_game_get_state(model->game) == TttMultiGameStateFinished) {
- if(ttt_multi_game_get_result(model->game) == TttMultiGameResultXWin) {
- status_str = "X win";
- } else if(ttt_multi_game_get_result(model->game) == TttMultiGameResultOWin) {
- status_str = "O win";
- } else if(ttt_multi_game_get_result(model->game) == TttMultiGameResultDraw) {
- status_str = "Draw";
- }
- } else {
- if(ttt_multi_game_current_player(model->game) == TttMultiGamePlayerX) {
- status_str = "X turn";
- } else {
- status_str = "O turn";
- }
- }
- } else {
- if(ttt_multi_game_get_state(model->game) == TttMultiGameStateFinished) {
- if(model->local_player == TttMultiGamePlayerX) {
- if(ttt_multi_game_get_result(model->game) == TttMultiGameResultXWin) {
- status_str = "You win";
- } else if(ttt_multi_game_get_result(model->game) == TttMultiGameResultOWin) {
- status_str = "You lose";
- } else if(ttt_multi_game_get_result(model->game) == TttMultiGameResultDraw) {
- status_str = "Draw";
- }
- } else {
- if(ttt_multi_game_get_result(model->game) == TttMultiGameResultXWin) {
- status_str = "You lose";
- } else if(ttt_multi_game_get_result(model->game) == TttMultiGameResultOWin) {
- status_str = "You win";
- } else if(ttt_multi_game_get_result(model->game) == TttMultiGameResultDraw) {
- status_str = "Draw";
- }
- }
- } else {
- if(model->local_player == TttMultiGamePlayerX) {
- if(ttt_multi_game_get_state(model->game) == TttMultiGameStateTurnX) {
- status_str = "Your turn";
- } else {
- status_str = "Opponent turn";
- }
- } else {
- if(ttt_multi_game_get_state(model->game) == TttMultiGameStateTurnO) {
- status_str = "Your turn";
- } else {
- status_str = "Opponent turn";
- }
- }
- }
- }
- elements_text_box(canvas, 64, 16, 64, 16, AlignCenter, AlignCenter, status_str, false);
- if(ttt_multi_game_get_state(model->game) == TttMultiGameStateFinished) {
- elements_multiline_text_aligned(
- canvas, 100, 32, AlignCenter, AlignTop, "Press OK\nto restart");
- }
- }
- static void ttt_multi_game_view_process_left(TttMultiGameView* view);
- static void ttt_multi_game_view_process_right(TttMultiGameView* view);
- static void ttt_multi_game_view_process_up(TttMultiGameView* view);
- static void ttt_multi_game_view_process_down(TttMultiGameView* view);
- static void ttt_multi_game_view_process_ok(TttMultiGameView* view);
- static bool ttt_multi_game_view_input_callback(InputEvent* event, void* context) {
- furi_assert(context);
- TttMultiGameView* game_view = context;
- bool consumed = false;
- if(event->type == InputTypeShort) {
- switch(event->key) {
- case InputKeyLeft:
- ttt_multi_game_view_process_left(game_view);
- consumed = true;
- break;
- case InputKeyRight:
- ttt_multi_game_view_process_right(game_view);
- consumed = true;
- break;
- case InputKeyUp:
- ttt_multi_game_view_process_up(game_view);
- consumed = true;
- break;
- case InputKeyDown:
- ttt_multi_game_view_process_down(game_view);
- consumed = true;
- break;
- case InputKeyOk:
- ttt_multi_game_view_process_ok(game_view);
- consumed = true;
- break;
- default:
- break;
- }
- }
- return consumed;
- }
- void ttt_multi_game_view_model_reset(TttMultiGameViewModel* model) {
- furi_assert(model);
- furi_assert(model->game);
- model->position_x = 1;
- model->position_y = 1;
- ttt_multi_game_reset(model->game);
- }
- TttMultiGameView* ttt_multi_game_view_alloc() {
- TttMultiGameView* game_view = malloc(sizeof(TttMultiGameView));
- game_view->view = view_alloc();
- view_set_context(game_view->view, game_view);
- view_allocate_model(game_view->view, ViewModelTypeLocking, sizeof(TttMultiGameViewModel));
- view_set_draw_callback(game_view->view, (ViewDrawCallback)ttt_multi_game_view_draw_callback);
- view_set_input_callback(game_view->view, ttt_multi_game_view_input_callback);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- model->game = ttt_multi_game_alloc();
- model->last_move = ttt_multi_game_move_alloc();
- ttt_multi_game_view_model_reset(model);
- },
- true);
- return game_view;
- }
- void ttt_multi_game_view_free(TttMultiGameView* game_view) {
- furi_assert(game_view);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- ttt_multi_game_free(model->game);
- ttt_multi_game_move_free(model->last_move);
- },
- true);
- view_free(game_view->view);
- free(game_view);
- }
- View* ttt_multi_game_get_view(TttMultiGameView* game_view) {
- furi_assert(game_view);
- return game_view->view;
- }
- void ttt_multi_game_view_process_up(TttMultiGameView* game_view) {
- furi_assert(game_view);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- if(model->position_y > 0) {
- model->position_y--;
- }
- },
- true);
- }
- void ttt_multi_game_view_process_down(TttMultiGameView* game_view) {
- furi_assert(game_view);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- if(model->position_y < 2) {
- model->position_y++;
- }
- },
- true);
- }
- void ttt_multi_game_view_process_left(TttMultiGameView* game_view) {
- furi_assert(game_view);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- if(model->position_x > 0) {
- model->position_x--;
- }
- },
- true);
- }
- void ttt_multi_game_view_process_right(TttMultiGameView* game_view) {
- furi_assert(game_view);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- if(model->position_x < 2) {
- model->position_x++;
- }
- },
- true);
- }
- void ttt_multi_game_view_process_ok(TttMultiGameView* game_view) {
- furi_assert(game_view);
- TttMultiGameViewCallback callback = NULL;
- void* context = NULL;
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- if(ttt_multi_game_get_state(model->game) == TttMultiGameStateFinished) {
- ttt_multi_game_view_model_reset(model);
- } else {
- model->last_move->player = ttt_multi_game_current_player(model->game);
- model->last_move->x = model->position_x;
- model->last_move->y = model->position_y;
- if(ttt_multi_game_is_move_valid(model->game, model->last_move)) {
- callback = model->callback;
- context = model->context;
- }
- }
- },
- true);
- if(callback) {
- callback(context, TttMultiCustomEventGameMove);
- }
- }
- void ttt_multi_game_view_move(TttMultiGameView* game_view, TttMultiGameMove* move) {
- furi_assert(game_view);
- furi_assert(move);
- TttMultiGameResult result;
- TttMultiGameViewCallback callback = NULL;
- void* context = NULL;
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- ttt_multi_game_make_move(model->game, move);
- result = ttt_multi_game_get_result(model->game);
- if(result != TttMultiGameResultNone) {
- callback = model->callback;
- context = model->context;
- }
- },
- true);
- if(callback) {
- callback(context, TttMultiCustomEventGameFinish);
- }
- }
- void ttt_multi_game_view_set_callback(
- TttMultiGameView* game_view,
- TttMultiGameViewCallback callback,
- void* context) {
- furi_assert(game_view);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- model->callback = callback;
- model->context = context;
- },
- true);
- }
- void ttt_multi_game_view_set_remote_play(TttMultiGameView* game_view, TttMultiGamePlayer player) {
- furi_assert(game_view);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- model->local_player = player;
- model->is_local = false;
- },
- true);
- }
- void ttt_multi_game_view_set_local_play(TttMultiGameView* game_view) {
- furi_assert(game_view);
- with_view_model(
- game_view->view, TttMultiGameViewModel * model, { model->is_local = true; }, true);
- }
- void ttt_multi_game_view_get_last_move(TttMultiGameView* game_view, TttMultiGameMove* move) {
- furi_assert(game_view);
- furi_assert(move);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- {
- if(model->last_move->player != TttMultiGamePlayerNone) {
- ttt_multi_game_move_copy(move, model->last_move);
- }
- },
- true);
- }
- TttMultiGameResult ttt_multi_game_view_get_result(TttMultiGameView* game_view) {
- furi_assert(game_view);
- TttMultiGameResult result = TttMultiGameResultNone;
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- { result = ttt_multi_game_get_result(model->game); },
- true);
- return result;
- }
- void ttt_multi_game_view_reset(TttMultiGameView* game_view) {
- furi_assert(game_view);
- with_view_model(
- game_view->view,
- TttMultiGameViewModel * model,
- { ttt_multi_game_view_model_reset(model); },
- true);
- }
|