aboutsummaryrefslogtreecommitdiff
path: root/ytz.c
blob: acfdfdefb38574215d75d10d7e3cb1d9bcdb6f2c (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
#include <stdint.h>
#include <stdio.h>

/*
   0000 0000 0000 0000 0000 0000 0000 0000
   rc         topscore  botflag. botscore.
     topflag x         x

   0000 0000 0000 0000 0000 0000 0000 0000
   xd4. d3.d 2.d1 .d0. prng state.... ....
*/

typedef struct {
	uint8_t topflag_w_roll;
	uint8_t topscore;
	uint8_t botflag;
	uint8_t botscore;
	uint16_t dice;
	uint16_t seed;
} ytz_state;

/* ROLLS */
#define GET_ROLL(s) ((uint8_t)((s & 0xC0) >> 6))  /* top 2 bits */
#define SET_ROLL(s, x) (s & 0x3F | ((uint8_t)x << 6))

/* TOP NUMBERS */
#define GET_NUM(s, x) ((uint8_t)((s & (1 << x)) >> x))
#define GET_ACE(s) (GET_NUM(s, 0))
#define GET_TWO(s) (GET_NUM(s, 1))
#define GET_THREE(s) (GET_NUM(s, 2))
#define GET_FOUR(s) (GET_NUM(s, 3))
#define GET_FIVE(s) (GET_NUM(s, 4))
#define GET_SIX(s) (GET_NUM(s, 5))

#define SET_NUM(s, x) (s | (1 << x))
#define SET_ACE(s) (SET_NUM(s, 0))
#define SET_TWO(s) (SET_NUM(s, 1))
#define SET_THREE(s) (SET_NUM(s, 2))
#define SET_FOUR(s) (SET_NUM(s, 3))
#define SET_FIVE(s) (SET_NUM(s, 4))
#define SET_SIX(s) (SET_NUM(s, 5))

/* DICE */
#define GET_D(s, x) ((uint8_t)((s & (0x07 << (3 * x))) >> (3 * x)))
#define GET_D0(s) (GET_D(s, 0))
#define GET_D1(s) (GET_D(s, 1))
#define GET_D2(s) (GET_D(s, 2))
#define GET_D3(s) (GET_D(s, 3))
#define GET_D4(s) (GET_D(s, 4))

#define SET_D(s, x, y) (s & (0xFFFF ^ (0x0007 << (3 * x))) | (y << (3 * x)))
#define SET_D0(s, y) (SET_D(s, 0, y))
#define SET_D1(s, y) (SET_D(s, 1, y))
#define SET_D2(s, y) (SET_D(s, 2, y))
#define SET_D3(s, y) (SET_D(s, 3, y))
#define SET_D4(s, y) (SET_D(s, 4, y))

/* 16-bit prng, with thanks/apologies to Dr. Lemire (https://lemire.me/blog/2019/07/03/a-fast-16-bit-random-number-generator/) */
uint32_t hash16(uint32_t input, uint32_t key) {
	uint32_t hash = input * key;
	return ((hash >> 16) ^ hash) & 0xFFFF;
}

uint16_t wyhash16(uint16_t* seed) {
	*seed += 0xfc15;
	return hash16(*seed, 0x2ab);
}

void init_ytz_state(ytz_state* state) {
	state->topflag_w_roll = 0x70;  /* roll 1, no flags */
	state->topscore = 0;
	state->botflag = 0;
	state->botscore = 0;
	state->dice = 0;
	state->seed = 13;  /* TODO this isn't random */
}

void main() {
	ytz_state y;
	init_ytz_state(&y);

	/*
	 * until the win condition is met
	 *  - roll all dice
	 *  - up to 2 times, ask user which dice to reroll
	 *  - ask user which category to mark it in
	 *  - validate and update state
	 *
	 *
	 */

	y.dice = SET_D0(y.dice, 1);
	y.dice = SET_D1(y.dice, 6);
	y.dice = SET_D2(y.dice, 4);
	y.dice = SET_D3(y.dice, 3);
	y.dice = SET_D4(y.dice, 2);

	printf("d1: %d\n", GET_D0(y.dice));
	printf("d2: %d\n", GET_D1(y.dice));
	printf("d3: %d\n", GET_D2(y.dice));
	printf("d4: %d\n", GET_D3(y.dice));
	printf("d5: %d\n", GET_D4(y.dice));
	printf("size: %d\n", sizeof(y));

	printf("roll: %d\n", GET_ROLL(y.topflag_w_roll));

	y.topflag_w_roll = SET_ROLL(y.topflag_w_roll, 2);
	printf("roll: %d\n", GET_ROLL(y.topflag_w_roll));

	printf("ace: %d\n", GET_ACE(y.topflag_w_roll));
	y.topflag_w_roll = SET_ACE(y.topflag_w_roll);
	printf("ace: %d\n", GET_ACE(y.topflag_w_roll));

	printf("seed: %d\n", y.seed);
	uint16_t hash;
	for (int i = 0; i < 10; i++) {
		hash = wyhash16(&(y.seed));
		printf("hash: %d\n", hash);
		printf("new seed: %d\n", y.seed);
	}

	hash = wyhash16(&(y.seed));
	printf("hash: %d\n", hash);
	printf("new seed: %d\n", y.seed);
}