1 /* game_util.c
2 *
3 *
4 * Copyright (C) 2020 Toxic All Rights Reserved.
5 *
6 * This file is part of Toxic.
7 *
8 * Toxic is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Toxic is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Toxic. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdint.h>
26
27 #include "game_util.h"
28 #include "toxic.h"
29 #include "windows.h"
30
game_util_get_direction(int key)31 Direction game_util_get_direction(int key)
32 {
33 switch (key) {
34 case KEY_UP: {
35 return NORTH;
36 }
37
38 case KEY_DOWN: {
39 return SOUTH;
40 }
41
42 case KEY_RIGHT: {
43 return EAST;
44 }
45
46 case KEY_LEFT: {
47 return WEST;
48 }
49
50 default: {
51 return INVALID_DIRECTION;
52 }
53 }
54 }
55
game_util_move_towards(const Coords * coords_a,const Coords * coords_b,bool inverse)56 Direction game_util_move_towards(const Coords *coords_a, const Coords *coords_b, bool inverse)
57 {
58 const int x1 = coords_a->x;
59 const int y1 = coords_a->y;
60 const int x2 = coords_b->x;
61 const int y2 = coords_b->y;
62
63 const int x_diff = abs(x1 - x2);
64 const int y_diff = abs(y1 - y2);
65
66 if (inverse) {
67 if (x_diff > y_diff) {
68 return x2 >= x1 ? WEST : EAST;
69 } else {
70 return y2 >= y1 ? NORTH : SOUTH;
71 }
72 } else {
73 if (x_diff > y_diff) {
74 return x2 < x1 ? WEST : EAST;
75 } else {
76 return y2 < y1 ? NORTH : SOUTH;
77 }
78 }
79 }
80
game_util_random_direction(void)81 Direction game_util_random_direction(void)
82 {
83 int r = rand() % 4;
84
85 switch (r) {
86 case 0:
87 return NORTH;
88
89 case 1:
90 return SOUTH;
91
92 case 2:
93 return EAST;
94
95 case 3:
96 return WEST;
97
98 default: // impossible
99 return NORTH;
100 }
101 }
102
game_util_move_coords(Direction direction,Coords * coords)103 void game_util_move_coords(Direction direction, Coords *coords)
104 {
105 switch (direction) {
106 case NORTH: {
107 if (coords->y > 0) {
108 --(coords->y);
109 }
110
111 break;
112 }
113
114 case SOUTH: {
115 ++(coords->y); // Will rollover if you do something stupid
116 break;
117 }
118
119 case EAST: {
120 ++(coords->x); // Will rollover if you do something stupid
121 break;
122 }
123
124 case WEST: {
125 if (coords->x > 0) {
126 --(coords->x);
127 }
128
129 break;
130 }
131
132 default: {
133 fprintf(stderr, "Warning: tried to move in an invalid direction\n");
134 return;
135 }
136 }
137 }
138
game_util_random_colour(void)139 int game_util_random_colour(void)
140 {
141 int r = rand() % 6;
142
143 switch (r) {
144 case 0:
145 return GREEN;
146
147 case 1:
148 return CYAN;
149
150 case 2:
151 return RED;
152
153 case 3:
154 return BLUE;
155
156 case 4:
157 return YELLOW;
158
159 case 5:
160 return MAGENTA;
161
162 default: // impossible
163 return RED;
164 }
165 }
166
net_pack_u16(uint8_t * bytes,uint16_t v)167 static size_t net_pack_u16(uint8_t *bytes, uint16_t v)
168 {
169 bytes[0] = (v >> 8) & 0xff;
170 bytes[1] = v & 0xff;
171 return sizeof(v);
172 }
173
net_unpack_u16(const uint8_t * bytes,uint16_t * v)174 static size_t net_unpack_u16(const uint8_t *bytes, uint16_t *v)
175 {
176 uint8_t hi = bytes[0];
177 uint8_t lo = bytes[1];
178 *v = ((uint16_t)hi << 8) | lo;
179 return sizeof(*v);
180 }
181
game_util_pack_u32(uint8_t * bytes,uint32_t v)182 size_t game_util_pack_u32(uint8_t *bytes, uint32_t v)
183 {
184 uint8_t *p = bytes;
185 p += net_pack_u16(p, (v >> 16) & 0xffff);
186 p += net_pack_u16(p, v & 0xffff);
187 return p - bytes;
188 }
189
game_util_unpack_u32(const uint8_t * bytes,uint32_t * v)190 size_t game_util_unpack_u32(const uint8_t *bytes, uint32_t *v)
191 {
192 const uint8_t *p = bytes;
193 uint16_t hi;
194 uint16_t lo;
195 p += net_unpack_u16(p, &hi);
196 p += net_unpack_u16(p, &lo);
197 *v = ((uint32_t)hi << 16) | lo;
198 return p - bytes;
199 }
200
201