the source code for the best KDL game ever (yet), hangman.
WIP, doesn't compile atm, must be changed to a module git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17658 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
8be1739f45
commit
7e6e175b9e
11
src/add-ons/kernel/debugger/Jamfile
Normal file
11
src/add-ons/kernel/debugger/Jamfile
Normal file
@ -0,0 +1,11 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel debugger ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
# UsePrivateHeaders drivers ;
|
||||
# UsePrivateHeaders kernel ;
|
||||
|
||||
|
||||
KernelAddon <kdebug>hangman : kernel debugger :
|
||||
hangman.c
|
||||
;
|
401
src/add-ons/kernel/debugger/hangman.c
Normal file
401
src/add-ons/kernel/debugger/hangman.c
Normal file
@ -0,0 +1,401 @@
|
||||
#ifdef _KERNEL_MODE
|
||||
#include <Drivers.h>
|
||||
#include <KernelExport.h>
|
||||
#endif
|
||||
#include <OS.h>
|
||||
#include <image.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* do we reboot on loose ? */
|
||||
//#define FAIL_IN_BSOD_CAUSE_REBOOT
|
||||
|
||||
/* shortcut to be able to exit (and take a screenshot) */
|
||||
#define CAN_EXIT_ON_HYPHEN
|
||||
|
||||
#define MAX_FAILS_BEFORE_BSOD 0
|
||||
|
||||
#define FORTUNE_FILE "/etc/fortunes/default"
|
||||
|
||||
#define DEV_ENTRY "misc/hangman"
|
||||
|
||||
#define KERNEL_IMAGE_ID 1
|
||||
|
||||
#define MIN_LETTERS 3
|
||||
#define MAX_LETTERS 10
|
||||
|
||||
#define MAX_CACHED_WORDS 5
|
||||
|
||||
char words[MAX_CACHED_WORDS][MAX_LETTERS+1];
|
||||
|
||||
/* design ripped off from http://www.latms.berkeley.k12.ca.us/perl/node30.html :) */
|
||||
static char hungman[] = \
|
||||
" ____ \n" \
|
||||
" | | \n" \
|
||||
" | %c \n" \
|
||||
" | %c%c%c \n" \
|
||||
" | %c %c \n" \
|
||||
" | \n";
|
||||
/* some colors */
|
||||
static char hungman_ansi[] = \
|
||||
" ____ \n" \
|
||||
" | | \n" \
|
||||
" | \033[36m%c\033[0m \n" \
|
||||
" | \033[35m%c%c%c\033[0m \n" \
|
||||
" | \033[35m%c %c\033[0m \n" \
|
||||
" | \n";
|
||||
|
||||
// for gets,
|
||||
#define BIGBUFFSZ 128
|
||||
char bigbuffer[BIGBUFFSZ];
|
||||
|
||||
#define BIT_FROM_LETTER(l) (0x1 << (l - 'a'))
|
||||
|
||||
status_t init_words(char *from);
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
|
||||
# ifdef __HAIKU__
|
||||
extern int kgets(char *buf, int len);
|
||||
# define PRINTF kprintf
|
||||
# define GETS(a) ({kprintf("hangman> "); kgets(a, sizeof(a));})
|
||||
# define HIDDEN_LETTER '_'
|
||||
# define HUNGMAN hungman_ansi
|
||||
# else
|
||||
/* BeOS R5 version, needs some R5 kernel privates... */
|
||||
/* the kernel pointer to the bsod_gets */
|
||||
static char *(*bsod_gets)(char *, char *, int);
|
||||
extern char *(*bsod_kgets)(char *, char *, int);
|
||||
//extern char *bsod_gets(char *);
|
||||
/* saved here before panic()ing */
|
||||
char *(*bsod_saved_kgets)(char *, char *, int);
|
||||
# define PRINTF kprintf
|
||||
# define GETS(a) ((*bsod_kgets)?(*bsod_kgets):(*bsod_gets))("hangman> ", a, sizeof(a))
|
||||
# define HIDDEN_LETTER '_'
|
||||
# define HUNGMAN hungman
|
||||
# endif
|
||||
#else
|
||||
/* userland version */
|
||||
# define PRINTF printf
|
||||
# define GETS(a) gets(a)
|
||||
# define dprintf printf
|
||||
# define HIDDEN_LETTER '.'
|
||||
# define HUNGMAN hungman_ansi
|
||||
#endif /* !_KERNEL_MODE */
|
||||
|
||||
status_t init_words(char *from)
|
||||
{
|
||||
int fd;
|
||||
size_t sz, got;
|
||||
int current, beg, end, i;
|
||||
struct stat st;
|
||||
|
||||
memset((void *)words, 0, sizeof(words));
|
||||
fd = open(from, O_RDONLY);
|
||||
if (fd < B_OK)
|
||||
return fd;
|
||||
/* lseek() seems to always return 0 from the kernel ??? */
|
||||
if (fstat(fd, &st))
|
||||
return B_ERROR;
|
||||
sz = (size_t)st.st_size;
|
||||
// sz = (size_t)lseek(fd, 0, SEEK_END);
|
||||
// dprintf("khangman: lseek(): %ld\n", sz);
|
||||
if (sz < 30) {
|
||||
dprintf("khangman: fortune file too small\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
// lseek(fd, 0, SEEK_SET);
|
||||
//srand((unsigned int)(system_time() + (system_time() >> 32) + find_thread(NULL)));
|
||||
srand((unsigned int)(system_time() & 0x0ffffffff));
|
||||
for (current = 0; current < MAX_CACHED_WORDS; current++) {
|
||||
off_t offset = (rand() % (sz - MAX_LETTERS));
|
||||
// dprintf("current %d, offset %ld\n", current, (long)offset);
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
got = read(fd, bigbuffer, BIGBUFFSZ - 2);
|
||||
// dprintf("--------------buff(%d):\n%20s\n", current, bigbuffer);
|
||||
for (beg = 0; beg < got && isalpha(bigbuffer[beg]); beg++);
|
||||
for (; beg < got && !isalpha(bigbuffer[beg]); beg++);
|
||||
if (beg + 1 < got && isalpha(bigbuffer[beg])) {
|
||||
for (end = beg; end < got && isalpha(bigbuffer[end]); end++);
|
||||
if (end < got && !isalpha(bigbuffer[end]) && beg + MIN_LETTERS < end) {
|
||||
/* got one */
|
||||
/* tolower */
|
||||
for (i = beg; i < end; i++)
|
||||
bigbuffer[i] = tolower(bigbuffer[i]);
|
||||
strncpy(&(words[current][0]), &(bigbuffer[beg]), end - beg);
|
||||
} else
|
||||
current--;
|
||||
} else
|
||||
current--;
|
||||
}
|
||||
close(fd);
|
||||
/*
|
||||
for (current = 0; current < MAX_CACHED_WORDS; current++)
|
||||
dprintf("%s\n", words[current]);
|
||||
*/
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void print_hangman(int fails)
|
||||
{
|
||||
PRINTF(HUNGMAN,
|
||||
(fails > 0)?'O':' ',
|
||||
(fails > 2)?'/':' ',
|
||||
(fails > 1)?'|':' ',
|
||||
(fails > 3)?'\\':' ',
|
||||
(fails > 4)?'/':' ',
|
||||
(fails > 5)?'\\':' ');
|
||||
}
|
||||
|
||||
void display_word(int current, uint32 tried_letters)
|
||||
{
|
||||
int i = 0;
|
||||
PRINTF("word> ");
|
||||
while (words[current][i]) {
|
||||
PRINTF("%c", (BIT_FROM_LETTER(words[current][i]) & tried_letters)?(words[current][i]):HIDDEN_LETTER);
|
||||
i++;
|
||||
}
|
||||
PRINTF("\n");
|
||||
}
|
||||
|
||||
int play_hangman(void)
|
||||
{
|
||||
int current;
|
||||
int score = 0;
|
||||
int bad_guesses;
|
||||
uint32 tried_letters;
|
||||
char *str;
|
||||
char try;
|
||||
int gotit, gotone;
|
||||
|
||||
for (current = 0; current < MAX_CACHED_WORDS; current++) {
|
||||
tried_letters = 0;
|
||||
gotit = 0;
|
||||
for (bad_guesses = 0; bad_guesses < 6; bad_guesses++) {
|
||||
do {
|
||||
gotit = 0;
|
||||
gotone = 1;
|
||||
display_word(current, tried_letters);
|
||||
str = GETS(bigbuffer);
|
||||
if (!str) {
|
||||
str = bigbuffer;
|
||||
PRINTF("buffer:%s\n", str);
|
||||
}
|
||||
#ifdef CAN_EXIT_ON_HYPHEN
|
||||
if (str[0] == '-') /* emergency exit */
|
||||
return 0;
|
||||
#endif
|
||||
if (!isalpha(str[0])) {
|
||||
PRINTF("not a letter\n");
|
||||
} else {
|
||||
try = tolower(str[0]);
|
||||
if (BIT_FROM_LETTER(try) & tried_letters) {
|
||||
PRINTF("%c already tried\n", try);
|
||||
} else {
|
||||
// REUSE
|
||||
str = words[current];
|
||||
gotit = 1;
|
||||
gotone = 0;
|
||||
tried_letters |= BIT_FROM_LETTER(try);
|
||||
while (*str) {
|
||||
if (!(BIT_FROM_LETTER(*str) & tried_letters))
|
||||
gotit=0;
|
||||
if (*str == try) {
|
||||
gotone = 1;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//PRINTF("gotone:%d, gotit:%d, tried_letters:%08lx\n", gotone, gotit, tried_letters);
|
||||
} while(tried_letters != 0x03ffffff && !gotit && gotone);
|
||||
if (gotit)
|
||||
break;
|
||||
print_hangman(bad_guesses+1);
|
||||
}
|
||||
if (bad_guesses < 6) {
|
||||
display_word(current, 0x03ffffff);
|
||||
if (strlen(words[current]) < 5)
|
||||
PRINTF("That was easy :-P\n");
|
||||
else if (strlen(words[current]) < 7)
|
||||
PRINTF("Good one !\n");
|
||||
else
|
||||
PRINTF("You got this hard one ! :-)\n");
|
||||
score ++;
|
||||
}
|
||||
/**/
|
||||
else return score;
|
||||
/**/
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
#ifdef _KERNEL_MODE /* driver parts */
|
||||
|
||||
typedef struct {
|
||||
int dummy;
|
||||
} cookie_t;
|
||||
|
||||
#ifndef __HAIKU__ /* BeOS intimacy revealed */
|
||||
//char *bsod_wrapper_gets(char *p, int len)
|
||||
//char *bsod_wrapper_gets(int len, char *p)
|
||||
char *bsod_wrapper_gets(char *prompt, char *p, int len)
|
||||
{
|
||||
/* fall back to the normal gets() */
|
||||
bsod_kgets = bsod_saved_kgets;
|
||||
// if (!bsod_kgets)
|
||||
// bsod_kgets = bsod_gets;
|
||||
/* and fake some typing */
|
||||
strcpy(p, fake_typed);
|
||||
return p;
|
||||
}
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
int kdlhangman(int argc, char **argv)
|
||||
{
|
||||
int score;
|
||||
score = play_hangman();
|
||||
PRINTF("score %d\n", score);
|
||||
if (score > (MAX_CACHED_WORDS - MAX_FAILS_BEFORE_BSOD)) {
|
||||
PRINTF("Congrats !\n");
|
||||
}
|
||||
if (score < (MAX_CACHED_WORDS - MAX_FAILS_BEFORE_BSOD)) {
|
||||
#ifdef FAIL_IN_BSOD_CAUSE_REBOOT
|
||||
PRINTF("Hmmm, sorry, need to trash your hdd... Ok, just a reboot then\n");
|
||||
fake_typed = "reboot";
|
||||
bsod_kgets = bsod_wrapper_gets;
|
||||
return 1;
|
||||
#else
|
||||
PRINTF("Hmmm, sorry, need to trash your hdd... Well, I'll be nice this time\n");
|
||||
#endif
|
||||
}
|
||||
//return B_KDEBUG_CONT;
|
||||
return B_KDEBUG_QUIT;
|
||||
}
|
||||
|
||||
const char * device_names[]={DEV_ENTRY, NULL};
|
||||
|
||||
status_t init_hardware(void) {
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t init_driver(void) {
|
||||
|
||||
if (init_words(FORTUNE_FILE) < B_OK) {
|
||||
dprintf("error reading fortune file\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
get_image_symbol(KERNEL_IMAGE_ID, "bsod_gets", B_SYMBOL_TYPE_ANY, (void **)&bsod_gets);
|
||||
add_debugger_command("kdlhangman", kdlhangman, "A funny KDL hangman game :-)");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void uninit_driver(void) {
|
||||
remove_debugger_command("kdlhangman", kdlhangman);
|
||||
}
|
||||
|
||||
const char **publish_devices() {
|
||||
return device_names;
|
||||
}
|
||||
|
||||
status_t khangman_open(const char *name, uint32 flags, cookie_t **cookie) {
|
||||
(void)name; (void)flags;
|
||||
*cookie = (void*)malloc(sizeof(cookie_t));
|
||||
if (*cookie == NULL) {
|
||||
dprintf("khangman_open : error allocating cookie\n");
|
||||
goto err0;
|
||||
}
|
||||
memset(*cookie, 0, sizeof(cookie_t));
|
||||
return B_OK;
|
||||
err0:
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t khangman_close(void *cookie) {
|
||||
(void)cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t khangman_free(cookie_t *cookie) {
|
||||
free(cookie);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t khangman_read(cookie_t *cookie, off_t position, void *data, size_t *numbytes) {
|
||||
*numbytes = 0;
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
status_t khangman_write(void *cookie, off_t position, const void *data, size_t *numbytes) {
|
||||
(void)cookie; (void)position; (void)data; (void)numbytes;
|
||||
//*numbytes = 0;
|
||||
/* here we get to kdlhangman */
|
||||
fake_typed = "kdlhangman";
|
||||
bsod_saved_kgets = bsod_kgets;
|
||||
bsod_kgets = bsod_wrapper_gets;
|
||||
kernel_debugger("So much more fun in KDL...");
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
device_hooks khangman_hooks={
|
||||
(device_open_hook)khangman_open,
|
||||
khangman_close,
|
||||
(device_free_hook)khangman_free,
|
||||
NULL,
|
||||
(device_read_hook)khangman_read,
|
||||
khangman_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
device_hooks *find_device(const char *name) {
|
||||
(void)name;
|
||||
return &khangman_hooks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
void kdl_trip(void)
|
||||
{
|
||||
int fd;
|
||||
fd = open("/dev/misc/hangman", O_WRONLY);
|
||||
if (fd < B_OK) {
|
||||
puts("hey, you're pissing me off, no /dev/"DEV_ENTRY" !!!");
|
||||
system("/bin/alert --stop 'It would work better with the hangman driver enabled...\nyou really deserves a forced reboot :P'");
|
||||
return;
|
||||
}
|
||||
write(fd, "hangme!", 7);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv)
|
||||
{
|
||||
int score; /* how many correct guesses ? */
|
||||
/* init */
|
||||
if (init_words(FORTUNE_FILE) < B_OK) {
|
||||
fprintf(stderr, "error reading fortune file\n");
|
||||
return 1;
|
||||
}
|
||||
score = play_hangman();
|
||||
PRINTF("score %d\n", score);
|
||||
if (score > (MAX_CACHED_WORDS - MAX_FAILS_BEFORE_BSOD)) {
|
||||
PRINTF("Congrats !\n");
|
||||
}
|
||||
if (score < (MAX_CACHED_WORDS - MAX_FAILS_BEFORE_BSOD)) {
|
||||
/* too many fails... gonna kick :p */
|
||||
kdl_trip();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user