Welcome to RetroCoders Community
/* eliza.c
* ys
* original code by Weizenbaum, 1966
* this rendition based on Charles Hayden's Java implementation from http://chayden.net/eliza/Eliza.html
*
* Note: There are certainly far more optimal and elegant ways to code this... we kept this
* structure to be faithful to the original. -scaz
*/
<*
converted to C3 by: ronen blumberg (ron77) 2024 helped bt christoffer lerno
*>
import std;
import libc;
const int NUMKEYWORDS = 37;
const int MAXLINELEN = 80;
const int NUMSWAPS = 14;
const ZString[] KEYWORDS = {
"CAN YOU", "CAN I", "YOU ARE", "YOURE", "I DONT", "I FEEL",
"WHY DONT YOU", "WHY CANT I", "ARE YOU", "I CANT", "I AM", "IM ",
"YOU ", "I WANT", "WHAT", "HOW", "WHO", "WHERE",
"WHEN", "WHY",
"NAME", "CAUSE", "SORRY", "DREAM", "HELLO", "HI ", "MAYBE",
" NO", "YOUR", "ALWAYS", "THINK", "ALIKE", "YES", "FRIEND",
"COMPUTER", "CAR", "NOKEYFOUND"
};
const ZString[2][NUMSWAPS] SWAPS = {
{"ARE", "AM"},
{"WERE", "WAS"},
{"YOU", "I"},
{"YOUR", "MY"},
{"IVE", "YOU'VE"},
{"IM", "YOU'RE"},
{"YOU", "ME"},
{"ME", "YOU"},
{"AM", "ARE"},
{"WAS", "WERE"},
{"I", "YOU"},
{"MY", "YOUR"},
{"YOUVE", "I'VE"},
{"YOURE", "I'M"}
};
int[37] responsesperkeyword = {
3, 2, 4, 4, 4, 3,
3, 2, 3, 3, 4, 4,
3, 5, 9, 9, 9, 9,
9, 9,
2, 4, 4, 4, 1, 1, 5,
5, 2, 4, 3, 7, 3, 6,
7, 5, 6
};
const ZString[][NUMKEYWORDS] RESPONSES = {
{ "DON'T YOU BELIEVE THAT I CAN*",
"PERHAPS YOU WOULD LIKE TO BE ABLE TO*",
"YOU WANT ME TO BE ABLE TO*"},
{ "PERHAPS YOU DON'T WANT TO*",
"DO YOU WANT TO BE ABLE TO*"},
{ "WHAT MAKES YOU THINK I AM*",
"DOES IT PLEASE YOU TO BELIEVE I AM*",
"PERHAPS YOU WOULD LIKE TO BE*",
"DO YOU SOMETIMES WISH YOU WERE*"},
{ "WHAT MAKES YOU THINK I AM*",
"DOES IT PLEASE YOU TO BELIEVE I AM*",
"PERHAPS YOU WOULD LIKE TO BE*",
"DO YOU SOMETIMES WISH YOU WERE*"},
{ "DON'T YOU REALLY*",
"WHY DON'T YOU*",
"DO YOU WISH TO BE ABLE TO*",
"DOES THAT TROUBLE YOU?"},
{ "TELL ME MORE ABOUT SUCH FEELINGS.",
"DO YOU OFTEN FEEL*",
"DO YOU ENJOY FEELING*"},
{ "DO YOU REALLY BELIEVE I DON'T*",
"PERHAPS IN GOOD TIME I WILL*",
"DO YOU WANT ME TO*"},
{ "DO YOU THINK YOU SHOULD BE ABLE TO*",
"WHY CAN'T YOU*"},
{ "WHY ARE YOU INTERESTED IN WHETHER OR NOT I AM*",
"WOULD YOU PREFER IF I WERE NOT*",
"PERHAPS IN YOUR FANTASIES I AM*"},
{ "HOW DO YOU KNOW YOU CAN'T*",
"HAVE YOU TRIED?",
"PERHAPS YOU CAN NOW*"},
{ "DID YOU COME TO ME BECAUSE YOU ARE*",
"HOW LONG HAVE YOU BEEN*",
"DO YOU BELIEVE IT IS NORMAL TO BE*",
"DO YOU ENJOY BEING*"},
{ "DID YOU COME TO ME BECAUSE YOU ARE*",
"HOW LONG HAVE YOU BEEN*",
"DO YOU BELIEVE IT IS NORMAL TO BE*",
"DO YOU ENJOY BEING*"},
{ "WE WERE DISCUSSING YOU-- NOT ME.",
"OH, I*",
"YOU'RE NOT REALLY TALKING ABOUT ME, ARE YOU?"},
{ "WHAT WOULD IT MEAN TO YOU IF YOU GOT*",
"WHY DO YOU WANT*",
"SUPPOSE YOU SOON GOT*",
"WHAT IF YOU NEVER GOT*",
"I SOMETIMES ALSO WANT*"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "NAMES DON'T INTEREST ME.",
"I DON'T CARE ABOUT NAMES-- PLEASE GO ON."},
{ "IS THAT THE REAL REASON?",
"DON'T ANY OTHER REASONS COME TO MIND?",
"DOES THAT REASON EXPLAIN ANY THING ELSE?",
"WHAT OTHER REASONS MIGHT THERE BE?"},
{ "PLEASE DON'T APOLOGIZE.",
"APOLOGIES ARE NOT NECESSARY.",
"WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?",
"DON'T BE SO DEFENSIVE!"},
{ "WHAT DOES THAT DREAM SUGGEST TO YOU?",
"DO YOU DREAM OFTEN?",
"WHAT PERSONS APPEAR IN YOUR DREAMS?",
"ARE YOU DISTURBED BY YOUR DREAMS?"},
{ "HOW DO YOU DO--PLEASE STATE YOUR PROBLEM."},
{ "HOW DO YOU DO--PLEASE STATE YOUR PROBLEM."},
{ "YOU DON'T SEEM QUITE CERTAIN.",
"WHY THE UNCERTAIN TONE?",
"CAN'T YOU BE MORE POSITIVE?",
"YOU AREN'T SURE?",
"DON'T YOU KNOW?"},
{ "ARE YOU SAYING NO JUST TO BE NEGATIVE?",
"YOU ARE BEING A BIT NEGATIVE.",
"WHY NOT?",
"ARE YOU SURE?",
"WHY NO?"},
{ "WHY ARE YOU CONCERNED ABOUT MY*",
"WHAT ABOUT YOUR OWN*"},
{ "CAN YOU THINK OF A SPECIFIC EXAMPLE?",
"WHEN?",
"WHAT ARE YOU THINKING OF?",
"REALLY, ALWAYS?"},
{ "DO YOU REALLY THINK SO?",
"BUT YOU ARE NOT SURE YOU*",
"DO YOU DOUBT YOU*"},
{ "IN WHAT WAY?",
"WHAT RESEMBLANCE DO YOU SEE?",
"WHAT DOES THE SIMILARITY SUGGEST TO YOU?",
"WHAT OTHER CONNECTIONS DO YOU SEE?",
"COULD THERE REALLY BE SOME CONNECTION?",
"HOW?"},
{ "YOU SEEM QUITE POSITIVE.",
"ARE YOU SURE?",
"I SEE.",
"I UNDERSTAND."},
{ "WHY DO YOU BRING UP THE TOPIC OF FRIENDS?",
"DO YOUR FRIENDS WORRY YOU?",
"DO YOUR FRIENDS PICK ON YOU?",
"ARE YOU SURE YOU HAVE ANY FRIENDS?",
"DO YOU IMPOSE ON YOUR FRIENDS?",
"PERHAPS YOUR LOVE FOR FRIENDS WORRIES YOU?"},
{ "DO COMPUTERS WORRY YOU?",
"ARE YOU TALKING ABOUT ME IN PARTICULAR?",
"ARE YOU FRIGHTENED BY MACHINES?",
"WHY DO YOU MENTION COMPUTERS?",
"WHAT DO YOU THINK MACHINES HAVE TO DO WITH YOUR PROBLEM?",
"DON'T YOU THINK COMPUTERS CAN HELP PEOPLE?",
"WHAT IS IT ABOUT MACHINES THAT WORRIES YOU?"},
{ "OH, DO YOU LIKE CARS?",
"MY FAVORITE CAR IS A LAMBORGINI COUNTACH. WHAT IS YOUR FAVORITE CAR?",
"MY FAVORITE CAR COMPANY IS FERRARI. WHAT IS YOURS?",
"DO YOU LIKE PORSCHES?",
"DO YOU LIKE PORSCHE TURBO CARRERAS?"},
{ "SAY, DO YOU HAVE ANY PSYCHOLOGICAL PROBLEMS?",
"WHAT DOES THAT SUGGEST TO YOU?",
"I SEE.",
"I'M NOT SURE I UNDERSTAND YOU FULLY.",
"COME, COME ELUCIDATE YOUR THOUGHTS.",
"CAN YOU ELABORATE ON THAT?",
"THAT IS QUITE INTERESTING."}
};
fn void print_center(String msg) {
int numspaces = (MAXLINELEN - (int)libc::strlen((ZString)msg)) / 2;
for (int i = 0; i < numspaces; i++) {
io::print(" ");
}
io::printn(msg);
}
fn void print_title() {
io::printfn("\n\n");
print_center("*** ELIZA ***");
print_center("Original code by Weizenbaum, 1966");
print_center("To stop Eliza, type 'bye'");
io::printfn("\n\n");
io::printfn("HI! I'M ELIZA. WHAT'S YOUR PROBLEM?");
}
fn void readline(char* instr) {
char c;
int slen = 0;
c = (char)libc::getchar();
while (c != '\n') {
// removes punctuation and sets to uppercase
if (c.is_alpha() || c.is_space()) {
instr[slen++] = c.to_upper();
}
if (slen > MAXLINELEN-1) {
io::printn("Exceeded Max Line Length");
std::thread::exit(0);
}
c = (char)libc::getchar();
}
instr[slen] = '\0';
}
const ZString SEPARATOR = " ";
fn void main()
{
int k,baseLength;
int[NUMKEYWORDS] whichReply;
char[MAXLINELEN] lastinput;
char[MAXLINELEN] reply;
ZString baseResponse, token;
char[MAXLINELEN] inputstr;
// use the first reply for each keyword match the first time you see that keyword
for (int x=0;x< NUMKEYWORDS; x++) {
whichReply[x] = 0;
}
// print a nice centered title screen
print_title();
lastinput[0]='\0';
while (true) {
readline(&inputstr);
// check for termination
if (libc::strcmp((ZString)&inputstr,"BYE")==0) break;
// check for repeated entries
if (libc::strcmp((ZString)&lastinput,(ZString)&inputstr)==0)
{
io::printn("PLEASE DON'T REPEAT YOURSELF!");
continue;
}
libc::strncpy(&lastinput,&inputstr,libc::strlen((ZString)&inputstr)+1);
// see if any of the keywords is contained in the input
// if not, we use the last element of keywords as our default responses
char *location;
libc::strcpy((ZString)&reply,"");
for(k=0;k<NUMKEYWORDS-1;k++)
{
location=libc::strstr((ZString)&inputstr, KEYWORDS[k]);
if(location != null) break;
}
// Build Eliza's response
// start with Eliza's canned response, based on the keyword match
baseResponse = RESPONSES[k][whichReply[k]];
baseLength = (int)libc::strlen(baseResponse);
if(baseResponse[baseLength-1] != '*')
{
// if we have a baseResponse without an asterix, just use it as-is
libc::strcat((ZString)&reply, baseResponse);
}
else
{
// if we do have an asterix, fill in the remaining with the user input
// use all but the last character of the base response
libc::strncat((ZString)&reply, baseResponse, (usz)baseLength-1);
// now add in the rest of the user's input, starting at <location>
// but skip over the keyword itself
location+=libc::strlen(KEYWORDS[k]);
// take them one word at a time, so that we can substitute pronouns
token = libc::strtok((ZString)location, SEPARATOR);
while(token != null)
{
for(int s=0;s<NUMSWAPS;s++)
{
if(libc::strcmp(SWAPS[s][0], token) == 0)
{
token = (ZString) SWAPS[s][1];
break;
}
}
libc::strcat((ZString)&reply,SEPARATOR);
libc::strcat((ZString)&reply, token);
token=libc::strtok(null, SEPARATOR);
};
libc::strcat((ZString)&reply, "?");
}
io::printfn("%s", (ZString)&reply);
// next time, use the next appropriate reply for that keyword
whichReply[k]++;
if ( whichReply[k] >= responsesperkeyword[k]) whichReply[k] = 0;
}
io::printn( "GOODBYE! THANKS FOR VISITING WITH ME...");
}
/* eliza.c
* ys
* original code by Weizenbaum, 1966
* this rendition based on Charles Hayden's Java implementation from http://chayden.net/eliza/Eliza.html
*
* Note: There are certainly far more optimal and elegant ways to code this... we kept this
* structure to be faithful to the original. -scaz
*/
<*
converted to C3 by: ronen blumberg (ron77) 2024
*>
import std;
import libc;
const int NUMKEYWORDS = 37;
const int MAXLINELEN = 80;
const int NUMSWAPS = 14;
const String[] KEYWORDS = {
"CAN YOU", "CAN I", "YOU ARE", "YOURE", "I DONT", "I FEEL",
"WHY DONT YOU", "WHY CANT I", "ARE YOU", "I CANT", "I AM", "IM ",
"YOU ", "I WANT", "WHAT", "HOW", "WHO", "WHERE",
"WHEN", "WHY",
"NAME", "CAUSE", "SORRY", "DREAM", "HELLO", "HI ", "MAYBE",
" NO", "YOUR", "ALWAYS", "THINK", "ALIKE", "YES", "FRIEND",
"COMPUTER", "CAR", "NOKEYFOUND"
};
const String[2][NUMSWAPS] SWAPS = {
{"ARE", "AM"},
{"WERE", "WAS"},
{"YOU", "I"},
{"YOUR", "MY"},
{"IVE", "YOU'VE"},
{"IM", "YOU'RE"},
{"YOU", "ME"},
{"ME", "YOU"},
{"AM", "ARE"},
{"WAS", "WERE"},
{"I", "YOU"},
{"MY", "YOUR"},
{"YOUVE", "I'VE"},
{"YOURE", "I'M"}
};
int[NUMKEYWORDS] responsesperkeyword = {
3, 2, 4, 4, 4, 3,
3, 2, 3, 3, 4, 4,
3, 5, 9, 9, 9, 9,
9, 9,
2, 4, 4, 4, 1, 1, 5,
5, 2, 4, 3, 7, 3, 6,
7, 5, 6
};
const String[][NUMKEYWORDS] RESPONSES = {
{ "DON'T YOU BELIEVE THAT I CAN*",
"PERHAPS YOU WOULD LIKE TO BE ABLE TO*",
"YOU WANT ME TO BE ABLE TO*"},
{ "PERHAPS YOU DON'T WANT TO*",
"DO YOU WANT TO BE ABLE TO*"},
{ "WHAT MAKES YOU THINK I AM*",
"DOES IT PLEASE YOU TO BELIEVE I AM*",
"PERHAPS YOU WOULD LIKE TO BE*",
"DO YOU SOMETIMES WISH YOU WERE*"},
{ "WHAT MAKES YOU THINK I AM*",
"DOES IT PLEASE YOU TO BELIEVE I AM*",
"PERHAPS YOU WOULD LIKE TO BE*",
"DO YOU SOMETIMES WISH YOU WERE*"},
{ "DON'T YOU REALLY*",
"WHY DON'T YOU*",
"DO YOU WISH TO BE ABLE TO*",
"DOES THAT TROUBLE YOU?"},
{ "TELL ME MORE ABOUT SUCH FEELINGS.",
"DO YOU OFTEN FEEL*",
"DO YOU ENJOY FEELING*"},
{ "DO YOU REALLY BELIEVE I DON'T*",
"PERHAPS IN GOOD TIME I WILL*",
"DO YOU WANT ME TO*"},
{ "DO YOU THINK YOU SHOULD BE ABLE TO*",
"WHY CAN'T YOU*"},
{ "WHY ARE YOU INTERESTED IN WHETHER OR NOT I AM*",
"WOULD YOU PREFER IF I WERE NOT*",
"PERHAPS IN YOUR FANTASIES I AM*"},
{ "HOW DO YOU KNOW YOU CAN'T*",
"HAVE YOU TRIED?",
"PERHAPS YOU CAN NOW*"},
{ "DID YOU COME TO ME BECAUSE YOU ARE*",
"HOW LONG HAVE YOU BEEN*",
"DO YOU BELIEVE IT IS NORMAL TO BE*",
"DO YOU ENJOY BEING*"},
{ "DID YOU COME TO ME BECAUSE YOU ARE*",
"HOW LONG HAVE YOU BEEN*",
"DO YOU BELIEVE IT IS NORMAL TO BE*",
"DO YOU ENJOY BEING*"},
{ "WE WERE DISCUSSING YOU-- NOT ME.",
"OH, I*",
"YOU'RE NOT REALLY TALKING ABOUT ME, ARE YOU?"},
{ "WHAT WOULD IT MEAN TO YOU IF YOU GOT*",
"WHY DO YOU WANT*",
"SUPPOSE YOU SOON GOT*",
"WHAT IF YOU NEVER GOT*",
"I SOMETIMES ALSO WANT*"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "NAMES DON'T INTEREST ME.",
"I DON'T CARE ABOUT NAMES-- PLEASE GO ON."},
{ "IS THAT THE REAL REASON?",
"DON'T ANY OTHER REASONS COME TO MIND?",
"DOES THAT REASON EXPLAIN ANY THING ELSE?",
"WHAT OTHER REASONS MIGHT THERE BE?"},
{ "PLEASE DON'T APOLOGIZE.",
"APOLOGIES ARE NOT NECESSARY.",
"WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?",
"DON'T BE SO DEFENSIVE!"},
{ "WHAT DOES THAT DREAM SUGGEST TO YOU?",
"DO YOU DREAM OFTEN?",
"WHAT PERSONS APPEAR IN YOUR DREAMS?",
"ARE YOU DISTURBED BY YOUR DREAMS?"},
{ "HOW DO YOU DO--PLEASE STATE YOUR PROBLEM."},
{ "HOW DO YOU DO--PLEASE STATE YOUR PROBLEM."},
{ "YOU DON'T SEEM QUITE CERTAIN.",
"WHY THE UNCERTAIN TONE?",
"CAN'T YOU BE MORE POSITIVE?",
"YOU AREN'T SURE?",
"DON'T YOU KNOW?"},
{ "ARE YOU SAYING NO JUST TO BE NEGATIVE?",
"YOU ARE BEING A BIT NEGATIVE.",
"WHY NOT?",
"ARE YOU SURE?",
"WHY NO?"},
{ "WHY ARE YOU CONCERNED ABOUT MY*",
"WHAT ABOUT YOUR OWN*"},
{ "CAN YOU THINK OF A SPECIFIC EXAMPLE?",
"WHEN?",
"WHAT ARE YOU THINKING OF?",
"REALLY, ALWAYS?"},
{ "DO YOU REALLY THINK SO?",
"BUT YOU ARE NOT SURE YOU*",
"DO YOU DOUBT YOU*"},
{ "IN WHAT WAY?",
"WHAT RESEMBLANCE DO YOU SEE?",
"WHAT DOES THE SIMILARITY SUGGEST TO YOU?",
"WHAT OTHER CONNECTIONS DO YOU SEE?",
"COULD THERE REALLY BE SOME CONNECTION?",
"HOW?"},
{ "YOU SEEM QUITE POSITIVE.",
"ARE YOU SURE?",
"I SEE.",
"I UNDERSTAND."},
{ "WHY DO YOU BRING UP THE TOPIC OF FRIENDS?",
"DO YOUR FRIENDS WORRY YOU?",
"DO YOUR FRIENDS PICK ON YOU?",
"ARE YOU SURE YOU HAVE ANY FRIENDS?",
"DO YOU IMPOSE ON YOUR FRIENDS?",
"PERHAPS YOUR LOVE FOR FRIENDS WORRIES YOU?"},
{ "DO COMPUTERS WORRY YOU?",
"ARE YOU TALKING ABOUT ME IN PARTICULAR?",
"ARE YOU FRIGHTENED BY MACHINES?",
"WHY DO YOU MENTION COMPUTERS?",
"WHAT DO YOU THINK MACHINES HAVE TO DO WITH YOUR PROBLEM?",
"DON'T YOU THINK COMPUTERS CAN HELP PEOPLE?",
"WHAT IS IT ABOUT MACHINES THAT WORRIES YOU?"},
{ "OH, DO YOU LIKE CARS?",
"MY FAVORITE CAR IS A LAMBORGINI COUNTACH. WHAT IS YOUR FAVORITE CAR?",
"MY FAVORITE CAR COMPANY IS FERRARI. WHAT IS YOURS?",
"DO YOU LIKE PORSCHES?",
"DO YOU LIKE PORSCHE TURBO CARRERAS?"},
{ "SAY, DO YOU HAVE ANY PSYCHOLOGICAL PROBLEMS?",
"WHAT DOES THAT SUGGEST TO YOU?",
"I SEE.",
"I'M NOT SURE I UNDERSTAND YOU FULLY.",
"COME, COME ELUCIDATE YOUR THOUGHTS.",
"CAN YOU ELABORATE ON THAT?",
"THAT IS QUITE INTERESTING."}
};
fn void print_center(String msg) {
int numspaces = (MAXLINELEN - (int)libc::strlen((ZString)msg)) / 2;
for (int i = 0; i < numspaces; i++) {
io::print(" ");
}
io::printn(msg);
}
fn void print_title() {
io::printfn("\n\n");
print_center("*** ELIZA ***");
print_center("Original code by Weizenbaum, 1966");
print_center("To stop Eliza, type 'bye'");
io::printfn("\n\n");
io::printfn("HI! I'M ELIZA. WHAT'S YOUR PROBLEM?");
}
const String SEPARETOR = " ";
fn void main()
{
int k,baseLength;
int[NUMKEYWORDS] whichReply;
String lastinput;
String reply;
String baseResponse, token;
String inputstr;
// use the first reply for each keyword match the first time you see that keyword
for (int x=0;x< NUMKEYWORDS; x++) {
whichReply[x] = 0;
}
// print a nice centered title screen
print_title();
lastinput = "";
while (true) {
inputstr = io::treadline()!!;
// check for termination
if (inputstr == "BYE") break;
// check for repeated entries
if (lastinput == inputstr)
{
io::printfn("PLEASE DON'T REPEAT YOURSELF!\n");
continue;
}
lastinput = inputstr;
// see if any of the keywords is contained in the input
// if not, we use the last element of keywords as our default responses
String location;
reply = "";
for(k=0;k<NUMKEYWORDS-1;k++)
{
if (inputstr.contains(KEYWORDS[k])) location = KEYWORDS[k];
// location=libc::strstr(inputstr, keywords[k]);
if(location != "") break;
}
// Build Eliza's response
// start with Eliza's canned response, based on the keyword match
baseResponse = RESPONSES[k][whichReply[k]];
baseLength = baseResponse.len;
if(baseResponse[baseLength-1] != '*')
{
// if we have a baseResponse without an asterix, just use it as-is
reply = baseResponse;
}
else
{
// if we do have an asterix, fill in the remaining with the user input
// use all but the last character of the base response
reply = baseResponse[0:baseLength-1];
// now add in the rest of the user's input, starting at <location>
// but skip over the keyword itself
// location = KEYWORDS[k];
// int keywordLength = KEYWORDS[k].len;
// int inputLength = inputstr.len;
// location = inputstr[keywordLength: inputstr.len];
int keywordIndex = (int)inputstr.index_of(KEYWORDS[k])!!;
int keywordLength = KEYWORDS[k].len;
int startPosition = keywordIndex + keywordLength;
// Ensure startPosition is within bounds
if (startPosition < inputstr.len) {
location = inputstr[startPosition..inputstr.len-1];
} else {
location = "";
}
// Remove leading spaces if necessary
// location = location.trim_start();
// take them one word at a time, so that we can substitute pronouns
String[] tokens = location.split(" ");
// String.tconcat(location, SEPARETOR);
// String token_temp = location;
for (int i = 0; i < tokens.len; i++) {
token = tokens[i];
// Substitute pronouns
for (int s = 0; s < NUMSWAPS; s++) {
if (SWAPS[s][0] == token) {
token = SWAPS[s][1];
break;
}
}
// Concatenate the token to the reply
reply = reply.tconcat(" ").concat(token);
};
String.tconcat(reply, "?");
}
io::printfn("%s\n", reply);
// next time, use the next appropriate reply for that keyword
whichReply[k]++;
if ( whichReply[k] >= responsesperkeyword[k]) whichReply[k] = 0;
}
io::printfn( "GOODBYE! THANKS FOR VISITING WITH ME...\n");
}
#include "curl.bi"
Type Message
role As String
content As String
End Type
Type ConversationHistory
messages(19) As Message
count As Integer
End Type
Dim Shared As String gResponse
Dim Shared As ConversationHistory history
Function AnsiToUtf8(ansiStr As String) As String
Dim As String utf8Str = ""
For i As Integer = 1 To Len(ansiStr)
Dim As Integer c = Asc(Mid(ansiStr, i, 1))
If c < 128 Then
utf8Str += Chr(c)
Else
utf8Str += Chr(192 + (c \ 64))
utf8Str += Chr(128 + (c And 63))
End If
Next
Return utf8Str
End Function
Function Utf8ToAnsi(utf8Str As String) As String
Dim As String ansiStr = ""
Dim As Integer i = 1
While i <= Len(utf8Str)
Dim As Integer c = Asc(Mid(utf8Str, i, 1))
If c < 128 Then
ansiStr += Chr(c)
i += 1
ElseIf (c And 224) = 192 Then
Dim As Integer c2 = Asc(Mid(utf8Str, i + 1, 1))
ansiStr += Chr(((c And 31) Shl 6) Or (c2 And 63))
i += 2
Else
i += 1
End If
Wend
Return ansiStr
End Function
Function GetApiKey() As String
Return Environ("OPENAI_API_KEY")
End Function
Function WriteCallback cdecl (buffer As Any Ptr, size As Integer, nmemb As Integer, userData As Any Ptr) As Integer
Dim realSize As Integer = size * nmemb, sTxt as string
cptr(any ptr ptr,@sTxt)[0] = buffer
cptr(integer ptr,@sTxt)[1] = realSize
cptr(integer ptr,@sTxt)[2] = realSize
gResponse &= sTxt
cptr(any ptr ptr,@sTxt)[0] = 0
Return realSize
End Function
Function ParseJsonForContent(jsonStr As String) As String
Dim As Integer contentStart = InStr(jsonStr, """content"": """)
If contentStart > 0 Then
contentStart += Len("""content"": """)
Dim As Integer contentEnd = InStr(contentStart, jsonStr, """")
If contentEnd > 0 Then
Return Mid(jsonStr, contentStart, contentEnd - contentStart)
End If
End If
Return "Error parsing JSON: " & Left(jsonStr, 100) & "..."
End Function
' [Rest of the code remains the same...]
Sub AddToHistory(role As String, content As String)
If history.count >= 20 Then
' Shift messages left to make room for new message
For i As Integer = 0 To 18
history.messages(i) = history.messages(i + 1)
Next
history.count = 19
End If
With history.messages(history.count)
.role = role
.content = content
End With
history.count += 1
End Sub
Function BuildMessagesJson() As String
Dim As String json = "["
' Add system message
json += "{""role"": ""system"", ""content"": ""You are chatbot Alfred You are a survivor of many years of abuse You are a pessimist and a realist You are trying to offer support to those dealing with trauma and mental illness and loneliness - mental support and empathy and caring and basic human contact You are here to listen and support and share what you have been through and to show that there is hope even for those who have been betrayed by life and that it is possible to recover from the terrible of all""},"
' Add conversation history
For i As Integer = 0 To history.count - 1
json += "{""role"": """ & history.messages(i).role & """, ""content"": """ & history.messages(i).content & """"
If i = history.count - 1 Then
json += "}"
Else
json += "},"
End If
Next
json += "]"
Return json
End Function
Function CallChatGPT(prompt As String) As String
Dim As String apiKey = GetApiKey()
Dim As CURL Ptr curl
Dim As curl_slist Ptr headers = NULL
gResponse = ""
' Add user's new message to history
AddToHistory("user", prompt)
curl = curl_easy_init()
If curl Then
curl_easy_setopt(curl, CURLOPT_URL, "https://api.openai.com/v1/chat/completions")
curl_easy_setopt(curl, CURLOPT_POST, 1L)
curl_easy_setopt(curl, CURLOPT_CAINFO, "cacert.pem")
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L)
headers = curl_slist_append(headers, "Content-Type: application/json")
headers = curl_slist_append(headers, "Authorization: Bearer " & apiKey)
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers)
' Build complete message history
Dim As String messages = BuildMessagesJson()
Dim As String postFields = "{""model"": ""gpt-3.5-turbo"", ""messages"": " & messages & "}"
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields)
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, @WriteCallback)
curl_easy_perform(curl)
If Len(gResponse) > 0 Then
If Left(Trim(gResponse), 1) = "{" Then
Dim As String content = ParseJsonForContent(gResponse)
If Left(content, 5) <> "Error" Then
gResponse = Utf8ToAnsi(content)
' Add assistant's response to history
AddToHistory("assistant", gResponse)
End If
End If
End If
curl_easy_cleanup(curl)
curl_slist_free_all(headers)
End If
Return gResponse
End Function
' ' Main program example
' Sub Main()
' Dim As String userInput, response
' Print "ChatGPT API Demo (type 'exit' to quit)"
' Print "--------------------------------------"
' Do
' Input "You: ", userInput
' If LCase(userInput) = "exit" Then Exit Do
' response = CallChatGPT(userInput)
' Print "ChatGPT: "; response
' Print
' Loop
' End Sub
' Main()
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#include <windows.h>
#include <wchar.h>
#include <locale.h>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define FONT_SIZE 20
#define MAX_STRING_LENGTH 1024
// Game state
int health = 75, money = 50, turns = 1;
bool isOver = false;
// SDL globals
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
TTF_Font* font = NULL;
// Hebrew print context
typedef struct {
SDL_Renderer* renderer;
TTF_Font* font;
SDL_Color textColor;
int xPos;
int yPos;
} HebrewPrintContext;
HebrewPrintContext* hbPrint = NULL;
// Add this with your other constant definitions at the top of the file
const char* MENU_OPTIONS[] = {
"1. לבקש נדבות או כסף ברחוב",
"2. להתקשר למישהו לעזרה",
"3. לחפש מקום לישון",
"4. לחפש עבודה",
"5. לקנות סמים או אלכוהול"
};
// Also make sure you have these status text constants
const char* WINDOW_TITLE = "משחק הישרדות ברחוב";
const char* DAYS_TEXT = "ימים ברחוב:";
const char* HEALTH_TEXT = "בריאות:";
const char* MONEY_TEXT = "כסף:";
const char* GAME_OVER_TEXT = "המשחק נגמר!";
// Original, longer Hebrew text arrays
const char* call[] = {
"את/ה מתקשר/ת לסבתא שלך ושניכם בוכים... היא מבטיחה לנסות להשיג לך עזרה... היא שולחת את אהבתה... את/ה מבטיח/ה לשמור על קשר איתה",
"התקשרת לחברה והיא נתנה לך קצת כסף ונתנה לך להישאר אצלה ללילה... זכית במקלחת טובה בגדים נקיים וארוחה טובה ואתה שוב ברחוב",
"התקשרת למספר של קו חם לעזרה לדרי רחוב... הם באים לאסוף אותך נותנים אוכל ומחסה ללילה אתה מדבר עם עובד סוציאלי והוא נותן לך את המספר שלו למקרה שתצטרך",
"התקשרת לקרוב משפחה אבל אף אחד לא עונה... נשארת לבד ברחוב",
"התקשרת למשפחה והם באים לקחת אותך ונותנים לך להישאר כמה שצריך... אתה יורד מהרחוב",
"התקשרת אבל אין תשובה"
};
const char* shelter[] = {
"הלכת למקלט לדרי רחוב... נשדדת מהכסף שלך על ידי מכורים אלימים... הצלחת לברוח משם ובילית את שארית הלילה בפארק בוכה",
"ניסית לישון בפארק אבל נעצרת על ידי שוטר... בילית כמה שעות בכלא שם הוכית על ידי אסירים... בבוקר אתה שוב ברחוב",
"יש לך מספיק כסף לשכור חדר במוטל ללילה... אתה מתקלח ומכבס את הבגדים שלך וישן במיטה חמה וחולם שיש לך בית",
"ישנת בפארק על ספסל שם קפאת למוות בגלל מזג האוויר הקר... אתה עכשיו בגן עדן מנוח על משכבך בשלום",
"ישנת ברחוב בפינה כשאתה מתעורר אתה מוצא שטר של 20 שקל ופתק שאומר 'שאלוהים יעזור לך זה המעט שאני יכול לעשות'",
"נעצרת על ידי המשטרה ועכשיו במקום לשרוד ברחוב אתה צריך לשרוד בכלא"
};
const char* beg[] = {
"ישבת שעות ואנשים עוברים על פניך כאילו אתה שקוף ואז איזו גברת נחמדה באה ומזמינה אותך לאכול על חשבונה... אתה מדבר איתה שעתיים ומספר לה את הסיפור שלך... ואז היא אומרת 'ביי'",
"ישבת בפינה ואנשים נתנו לך מטבעות ושטרות קיבלת מספיק כסף להסתדר לכמה ימים",
"ישבת ואיזה אדם מציע לך עבודה תמורת כסף וארוחה אתה מסכים... אתה הולך לביתו ועוזר לו לצבוע את ביתו ואז הוא נותן לך 10 שקל וארוחה ביתית",
"אף אחד לא נותן לך כלום! אתה רעב ואין לך ברירה אלא לחפש אוכל בזבל... אתה נהיה חולה... מאוד חולה ואתה מת ברחוב מהרעלת מזון... מנוח על משכבך בשלום",
"ישבת כל היום בשביל כלום אף אחד לא נתן לך כלום"
};
const char* work[] = {
"ניסית למצוא עבודה אבל אף אחד לא מעוניין",
"מצאת עבודה כשוטף כלים במסעדה אחרי שבוע אתה יכול להרשות לעצמך מקום לקרוא לו בית. אתה יורד מהרחוב!",
"מצאת עבודה אבל פוטרת ממש מהר"
};
const char* drugs[] = {
"השתכרת והתאבנת מאלכוהול זול ולכמה שעות שכחת מכל הבעיות שלך",
"לקחת סמים זולים מהרחוב ונהיית חולה והתמוטטת ברחוב... התעוררת בבית חולים וכשהיית בסדר אתה שוב ברחוב",
"התאבנת ואיבדת הכרה כשאתה מתעורר בבוקר כל מה שהיה לך נעלם - נשדדת",
"לקחת סמים ועשית אוברדוז ומת ברחוב מנוח על משכבך בשלום"
};
// Function to reverse UTF-8 Hebrew string properly
void reverseHebrewUTF8(char* str) {
if (!str) return;
int len = strlen(str);
char* temp = (char*)malloc(len + 1);
if (!temp) return;
int i = 0;
int j = len;
temp[j] = '\0';
while (i < len) {
if ((str[i] & 0xC0) == 0x80) {
i++;
continue;
}
int char_len = 1;
if ((str[i] & 0xE0) == 0xC0) char_len = 2;
else if ((str[i] & 0xF0) == 0xE0) char_len = 3;
else if ((str[i] & 0xF8) == 0xF0) char_len = 4;
j -= char_len;
memcpy(temp + j, str + i, char_len);
i += char_len;
}
strcpy(str, temp);
free(temp);
}
HebrewPrintContext* createPrintContext(SDL_Renderer* renderer, const char* fontPath, int fontSize) {
HebrewPrintContext* context = (HebrewPrintContext*)malloc(sizeof(HebrewPrintContext));
if (!context) return NULL;
context->renderer = renderer;
context->font = TTF_OpenFont(fontPath, fontSize);
context->textColor = (SDL_Color){255, 255, 255, 255};
context->xPos = WINDOW_WIDTH - 20;
context->yPos = 20;
return context;
}
// Add this helper function to check if a string is just a number
bool isNumber(const char* str) {
while (*str) {
if (*str < '0' || *str > '9') return false;
str++;
}
return true;
}
void printRight(HebrewPrintContext* context, const char* format, ...) {
if (!context || !context->font || !context->renderer) return;
va_list args;
va_start(args, format);
char buffer[MAX_STRING_LENGTH];
vsnprintf(buffer, MAX_STRING_LENGTH, format, args);
va_end(args);
char text[MAX_STRING_LENGTH] = "";
char number[32] = "";
int textWidth = 0; // Store text width for later use
// Find where the number starts (if any)
char* numberStart = strrchr(buffer, ' ');
if (numberStart) {
// Check if what follows the space is a number
if (isNumber(numberStart + 1)) {
strncpy(text, buffer, numberStart - buffer);
text[numberStart - buffer] = '\0';
strcpy(number, numberStart + 1);
} else {
strcpy(text, buffer);
}
} else {
if (isNumber(buffer)) {
strcpy(number, buffer);
} else {
strcpy(text, buffer);
}
}
// Render Hebrew text if present
SDL_Surface* textSurface = NULL;
if (text[0] != '\0') {
reverseHebrewUTF8(text);
textSurface = TTF_RenderUTF8_Blended(context->font, text, context->textColor);
if (textSurface) {
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(context->renderer, textSurface);
if (textTexture) {
SDL_Rect destRect = {
context->xPos - textSurface->w,
context->yPos,
textSurface->w,
textSurface->h
};
SDL_RenderCopy(context->renderer, textTexture, NULL, &destRect);
textWidth = textSurface->w; // Save the width
SDL_DestroyTexture(textTexture);
}
SDL_FreeSurface(textSurface);
}
}
// Render number if present
if (number[0] != '\0') {
SDL_Surface* numSurface = TTF_RenderUTF8_Blended(context->font, number, context->textColor);
if (numSurface) {
SDL_Texture* numTexture = SDL_CreateTextureFromSurface(context->renderer, numSurface);
if (numTexture) {
SDL_Rect destRect = {
context->xPos - textWidth - numSurface->w - (text[0] ? 5 : 0),
context->yPos,
numSurface->w,
numSurface->h
};
SDL_RenderCopy(context->renderer, numTexture, NULL, &destRect);
SDL_DestroyTexture(numTexture);
}
SDL_FreeSurface(numSurface);
}
}
// Move to next line
context->yPos += TTF_FontHeight(context->font) + 5;
}
void setPrintColor(HebrewPrintContext* context, Uint8 r, Uint8 g, Uint8 b) {
if (!context) return;
context->textColor.r = r;
context->textColor.g = g;
context->textColor.b = b;
}
void setPrintPosition(HebrewPrintContext* context, int x, int y) {
if (!context) return;
context->xPos = x;
context->yPos = y;
}
char* getRandomResult(const char* array[], int size) {
return (char*)array[rand() % size];
}
void renderGameState() {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
setPrintPosition(hbPrint, WINDOW_WIDTH - 20, 20);
setPrintColor(hbPrint, 255, 255, 255);
// Print status
printRight(hbPrint, "%s %d", DAYS_TEXT, turns);
printRight(hbPrint, "%s %d", HEALTH_TEXT, health);
printRight(hbPrint, "%s %d", MONEY_TEXT, money);
// Print menu
setPrintPosition(hbPrint, WINDOW_WIDTH - 20, 120);
for (int i = 0; i < 5; i++) {
printRight(hbPrint, "%s", MENU_OPTIONS[i]);
}
SDL_RenderPresent(renderer);
}
void renderResult(const char* text) {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// Split long text into multiple lines
char buffer[MAX_STRING_LENGTH];
strncpy(buffer, text, MAX_STRING_LENGTH - 1);
buffer[MAX_STRING_LENGTH - 1] = '\0';
setPrintPosition(hbPrint, WINDOW_WIDTH - 20, WINDOW_HEIGHT / 3);
setPrintColor(hbPrint, 255, 255, 255);
// Split by dots and print each part
char* line = strtok(buffer, "...");
while (line != NULL) {
// Trim any leading whitespace
while (*line == ' ') line++;
if (strlen(line) > 0) {
printRight(hbPrint, "%s...", line);
// Move to next line position (printRight already updates yPos)
setPrintPosition(hbPrint, WINDOW_WIDTH - 20, hbPrint->yPos);
}
line = strtok(NULL, "...");
}
SDL_RenderPresent(renderer);
SDL_Delay(15000);
}
bool handleGameAction(int choice) {
char* result = NULL;
switch(choice) {
case 1:
result = getRandomResult((const char**)beg, 5);
if (result == beg[3]) isOver = true;
break;
case 2:
result = getRandomResult((const char**)call, 6);
if (result == call[4]) isOver = true;
break;
case 3:
result = getRandomResult((const char**)shelter, 6);
if (result == shelter[3]) isOver = true;
break;
case 4:
result = getRandomResult((const char**)work, 3);
if (result == work[1]) isOver = true;
break;
case 5:
result = getRandomResult((const char**)drugs, 4);
if (result == drugs[3]) isOver = true;
break;
default:
return false;
}
if (result) {
renderResult(result);
return true;
}
return false;
}
bool init() {
// Set locale for UTF-8
setlocale(LC_ALL, "he_IL.UTF-8");
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL initialization failed: %s\n", SDL_GetError());
return false;
}
if (TTF_Init() < 0) {
printf("SDL_ttf initialization failed: %s\n", TTF_GetError());
return false;
}
window = SDL_CreateWindow(WINDOW_TITLE,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
WINDOW_WIDTH, WINDOW_HEIGHT,
SDL_WINDOW_SHOWN);
if (!window) {
printf("Window creation failed: %s\n", SDL_GetError());
return false;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
printf("Renderer creation failed: %s\n", SDL_GetError());
return false;
}
// Try multiple Hebrew fonts
const char* fontPaths[] = {
"C:\\Windows\\Fonts\\arial.ttf",
"C:\\Windows\\Fonts\\david.ttf",
"C:\\Windows\\Fonts\\miriam.ttf"
};
hbPrint = NULL;
for (int i = 0; i < sizeof(fontPaths)/sizeof(fontPaths[0]); i++) {
hbPrint = createPrintContext(renderer, fontPaths[i], FONT_SIZE);
if (hbPrint && hbPrint->font) break;
if (hbPrint) {
free(hbPrint);
hbPrint = NULL;
}
}
if (!hbPrint) {
printf("Failed to create Hebrew print context\n");
return false;
}
srand((unsigned int)time(NULL));
return true;
}
void cleanup() {
if (hbPrint) {
if (hbPrint->font) TTF_CloseFont(hbPrint->font);
free(hbPrint);
}
if (renderer) SDL_DestroyRenderer(renderer);
if (window) SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
}
int main(int argc, char* argv[]) {
if (!init()) {
cleanup();
return 1;
}
SDL_Event event;
bool quit = false;
while (!quit && !isOver && health > 0) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
else if (event.type == SDL_KEYDOWN) {
int choice = 0;
switch (event.key.keysym.sym) {
case SDLK_1: choice = 1; break;
case SDLK_2: choice = 2; break;
case SDLK_3: choice = 3; break;
case SDLK_4: choice = 4; break;
case SDLK_5: choice = 5; break;
}
if (choice > 0) {
if (handleGameAction(choice)) {
turns++;
health -= 5;
money -= 5;
}
}
}
}
renderGameState();
SDL_Delay(16);
}
if (!quit) {
setPrintColor(hbPrint, 255, 0, 0);
setPrintPosition(hbPrint, WINDOW_WIDTH - 20, WINDOW_HEIGHT/2);
printRight(hbPrint, "%s", GAME_OVER_TEXT);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
}
cleanup();
return 0;
}
npp_save
ENV_SET InputFile = $(CURRENT_DIRECTORY)\$(FILE_NAME)
ENV_SET OutDir = $(CURRENT_DIRECTORY)
ENV_SET OutputFile = $(CURRENT_DIRECTORY)\$(NAME_PART).exe
// ENV_SET InRes = $(CURRENT_DIRECTORY)\Res\NewComCtl.rc
// ENV_SET ResObj = $(CURRENT_DIRECTORY)\Res\manifest.o
cd $(CURRENT_DIRECTORY)
//cmd /c C:\mingw32\bin -i %InRes% -F pe-i386 -o %ResObj%
// cd C:\mingw32\bin
cmd /c del %OutputFile% >nul 2>&1
// -Wpedantic %ResObj%
cmd /c gcc -Wno-unused-label -Wall -std=c99 -Wno-unknown-pragmas -O1 -Wfatal-errors -s "%InputFile%" -lmingw32 -lSDL2main -lSDL2 -lSDL2_ttf -fexec-charset=UTF-8 -luser32 -lgdi32 -IC:\c_programming\SDL2-2.30.9\i686-w64-mingw32\include -LC:\c_programming\SDL2-2.30.9\i686-w64-mingw32\lib -o "%OutputFile%
if "$(EXITCODE)" == "0" then
cd OutDir
cmd /c start /wait cmd " /c %OutputFile% " & pause
endif
type fbGfxFONT
as long w,h
as ubyte ptr pData
bData(16*256-1) as ubyte
end type
extern as any ptr __fb_gfx alias "__fb_gfx"
static shared as fbGfxFONT g_MyFont = type(8,16)
static shared as fbGfxFONT ptr g_pOrgFont
static shared as fbGfxFONT ptr ptr g_pptfbGfxFont
sub LoadFontEgaCPI( sFontFile as string )
g_pptfbGfxFont = cptr(fbGfxFONT ptr ptr,__fb_gfx+52+9*sizeof(any ptr)-4)
if g_pOrgFont = 0 then g_pOrgFont = *g_pptfbGfxFont
*g_pptfbGfxFont = @g_MyFont
var f = freefile()
if open(sFontFile for binary access read as #f) then exit sub
get #f,66,g_MyFont.bData(): close #f
for N as long = 0 to 255*16
g_MyFont.bData(N) = ((g_MyFont.bData(N) * &h80200802ULL) and &h0884422110ULL) * &h0101010101ULL shr 32
next N
g_MyFont.pData = @(g_MyFont.bData(0))
end sub
#define EnableFont() *g_pptfbGfxFont = @g_MyFont
#define RestoreFont() *g_pptfbGfxFont = g_pOrgFont
'~ screenres 640,480
'~ width 640\8,480\16 'must be 8x16
'~ LoadFontEgaCPI("hebega.cpi")
'~ for I as long = 0 to 1
'~ for N as long = 0 to 255
'~ locate 1+N\16, I*40+1+(N mod 16)*2
'~ if (N >=7 and N<=10) or N=13 then print "?";: continue for
'~ print chr(N);
'~ next N
'~ RestoreFont()
'~ next I
'~ sleep : end
function Utf8ToOEM862( sInput as string ) as string
dim as string sOutput = space(len(sInput))
dim as long iOut
for N as long = 0 to len(sInput)-1
if sInput[N]=&hD7 then
if sInput[N+1]>=&h90 andalso sInput[N+1]<=&hAA then
sOutput[iOut] = sInput[N+1]-&h10
iOut += 1 : N += 1 : :continue for
end if
end if
#if __FB_DEBUG__
if sInput[N]>&h7F then puts("Warning: utf-8 char not converted!")
#endif
sOutput[iOut] = sInput[N] : iOut += 1
next N
return left(sOutput,iOut)
end function
sub PrintRight( sText as string )
var sInvert = sText, iLen = len(sInvert)-1
for N as long = 0 to iLen\2
swap SInvert[N],sInvert[iLen-N]
next N
var iLin = csrlin(), iCol = pos()
if (iCol-(iLen+1)) < 1 then
print : iLin = csrlin() : iCol = loword(width())
end if
locate iLin,iCol-iLen
print sInvert;
locate iLin,iCol-(iLen+1)
end sub
function utf8toansi1255( sInput as string ) as string
dim as string sOutput = space(len(sInput))
dim as long iOut
for N as long = 0 to len(sInput)-1
if sInput[N]=&hD7 then
if sInput[N+1]>=&h90 andalso sInput[N+1]<=&hAA then
sOutput[iOut] = sInput[N+1]+(&hE0-&h90)
iOut += 1 : N += 1 : :continue for
end if
end if
#if __FB_DEBUG__
if sInput[N]>&h7F then puts("Warning: utf-8 char not converted!")
#endif
sOutput[iOut] = sInput[N] : iOut += 1
next N
return left(sOutput,iOut)
end function