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