aboutsummaryrefslogtreecommitdiff
path: root/src/sdl/action.c
blob: bc0cf89baf8b937f3dcd8896eaf25497a5b72caf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "../core/sok.h"
#include "action.h"
#include "solve.h"
#include "game-state.h"
#include "util.h"

#define CASE_DIGIT \
  case SDLK_0: \
  case SDLK_1: \
  case SDLK_2: \
  case SDLK_3: \
  case SDLK_4: \
  case SDLK_5: \
  case SDLK_6: \
  case SDLK_7: \
  case SDLK_8: \
  case SDLK_9:

#define CASE_DIR \
  case SDLK_UP: \
  case SDLK_DOWN: \
  case SDLK_LEFT: \
  case SDLK_RIGHT: \
  case SDLK_h: \
  case SDLK_j: \
  case SDLK_k: \
  case SDLK_l:

static sok_dir_t
keycode_to_dir(const SDL_Keycode code) {
  switch (code) {
  case SDLK_UP:     return SOK_DIR_UP;
  case SDLK_k:      return SOK_DIR_UP;
  case SDLK_LEFT:   return SOK_DIR_LEFT;
  case SDLK_h:      return SOK_DIR_LEFT;
  case SDLK_DOWN:   return SOK_DIR_DOWN;
  case SDLK_j:      return SOK_DIR_DOWN;
  case SDLK_RIGHT:  return SOK_DIR_RIGHT;
  case SDLK_l:      return SOK_DIR_RIGHT;
  default:          return SOK_DIR_LAST;
  }
}

static action_t
get_key_action(
  const SDL_Keycode code
) {
  switch (code) {
  case SDLK_ESCAPE:
  case SDLK_q:
    return (action_t) { .type = ACTION_QUIT };
  CASE_DIR
    return (action_t) {
      .type = ACTION_MOVE,
      .data = keycode_to_dir(code)
    };
  case SDLK_u:
    return (action_t) { .type = ACTION_UNDO };
  case SDLK_SPACE:
    return (action_t) { .type = ACTION_NEXT };
  CASE_DIGIT
    return (action_t) {
      .type = ACTION_WARP_BUF_PUSH,
      .data = (code - SDLK_0),
    };
  case SDLK_DELETE:
    return (action_t) { .type = ACTION_WARP_BUF_POP };
  case SDLK_RETURN:
    return (action_t) { .type = ACTION_WARP };
  case SDLK_r:
    return (action_t) { .type = ACTION_RESET };
  case SDLK_s:
    return (action_t) { .type = ACTION_SOLVE };
  case SDLK_EQUALS:
    return (action_t) { .type = ACTION_ZOOM_IN, .data = 1 };
  case SDLK_MINUS:
    return (action_t) { .type = ACTION_ZOOM_OUT, .data = -1 };
  case SDLK_F11:
    return (action_t) { .type = ACTION_FULLSCREEN };
  default:
    return (action_t) { .type = ACTION_NONE };
  }
}

static action_t
get_wheel_action(
  const Sint32 y
) {
  if (y > 0) {
    return (action_t) { .type = ACTION_ZOOM_IN, .data = y };
  } else if (y < 0) {
    return (action_t) { .type = ACTION_ZOOM_OUT, .data = -y };
  } else {
    return (action_t) { .type = ACTION_NONE };
  }
}

action_t
get_action(
  const game_state_t state,
  const SDL_Event * const ev,
  const Uint32 solve_event_type
) {
  switch (ev->type) {
  case SDL_QUIT:
    return (action_t) { .type = ACTION_QUIT };
    break;
  case SDL_MOUSEWHEEL:
    return get_wheel_action(ev->wheel.y);
    break;
  case SDL_KEYUP:
    if (state == GAME_STATE_SOLVE) {
      return (action_t) { .type = ACTION_SOLVE_CANCEL };
    } else {
      return get_key_action(ev->key.keysym.sym);
    }
    break;
  default:
    if (state == GAME_STATE_SOLVE && ev->type == solve_event_type) {
      switch (ev->user.code) {
      case SOLVE_EVENT_STEP:
        return (action_t) {
          .type = ACTION_SOLVE_EVENT_STEP,
          .data = solve_get_num_steps(ev->user.data1),
        };
        break;
      case SOLVE_EVENT_FAIL:
        warn("solve failed: %s", ev->user.data2 ? (char*) ev->user.data2 : "unknown error");
        return (action_t) { .type = ACTION_SOLVE_EVENT_FAIL };
        break;
      case SOLVE_EVENT_DONE:
        return (action_t) { .type = ACTION_SOLVE_EVENT_DONE };
        break;
      default:
        // ignore event
        break;
      }
    }
  }

  // ignore event
  return (action_t) { .type = ACTION_NONE };
}