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…
x
Reference in New Issue
Block a user