Skip to content

Instantly share code, notes, and snippets.

@andhieka
Last active June 4, 2020 08:09
Show Gist options
  • Save andhieka/4a8c5eea916e87a77378e5110840d397 to your computer and use it in GitHub Desktop.
Save andhieka/4a8c5eea916e87a77378e5110840d397 to your computer and use it in GitHub Desktop.
MysteryGame - Completed with State Pattern
import 'dart:io';
abstract class GameState {
String getPrompt();
void process(String input, MysteryGame game);
}
//#region Concrete states
class TheKitchenGameState extends GameState {
static const List<String> KITCHEN_ACTION_LIST = [
'chop',
'chop',
'chop',
'chop',
'chop',
'fry',
'serve',
];
int completedKitchenActionIndex = 0;
@override
String getPrompt() {
if (completedKitchenActionIndex == 0) {
return 'Welcome to The Kitchen. Do your actions without mistake!';
}
}
@override
void process(String input, MysteryGame game) {
if (input == KITCHEN_ACTION_LIST[completedKitchenActionIndex]) {
completedKitchenActionIndex++;
if (completedKitchenActionIndex == KITCHEN_ACTION_LIST.length) {
game.state = DanceStudioGameState();
}
} else {
game.state = DeadGameState();
}
}
}
class DanceStudioGameState extends GameState {
static const List<String> DANCE_ACTIONS = [
'left',
'right',
'jump',
'jump',
];
int completedDanceActionIndex = 0;
@override
String getPrompt() {
if (completedDanceActionIndex == 0) {
return 'Welcome to the Dance Studio! Do the secret dance to pass.';
}
return null;
}
@override
void process(String input, MysteryGame game) {
if (input == DANCE_ACTIONS[completedDanceActionIndex]) {
completedDanceActionIndex++;
if (completedDanceActionIndex == DANCE_ACTIONS.length) {
game.state = MusicStudioGameState();
}
} else {
game.state = DeadGameState();
}
}
}
class MusicStudioGameState extends GameState {
DateTime lastInputTime;
int baseIntervalMs;
static const List<String> NOTES = [
'c', 'c', 'd', 'c', 'f', 'e'
];
int completedNoteIndex = 0;
int retriesAllowed = 3;
@override
String getPrompt() {
if (completedNoteIndex == 0) {
return "Sing happy birthday in C! (pretend all notes are quarter notes)";
}
return null;
}
@override
void process(String input, MysteryGame game) {
if (input == NOTES[completedNoteIndex]) {
if (_isTempoAcceptable()) {
completedNoteIndex++;
lastInputTime = DateTime.now();
if (completedNoteIndex == NOTES.length) {
game.state = SuccessGameState();
}
} else {
print('Wrong tempo!');
_reset();
}
} else {
if (retriesAllowed == 0) {
game.state = DeadGameState();
} else {
_reset();
}
}
}
void _reset() {
retriesAllowed--;
completedNoteIndex = 0;
baseIntervalMs = null;
lastInputTime = null;
}
bool _isTempoAcceptable() {
if (lastInputTime == null) {
// no need to check first note
return true;
}
DateTime now = DateTime.now();
int intervalInMs = now.millisecondsSinceEpoch - lastInputTime.millisecondsSinceEpoch;
if (baseIntervalMs == null) {
// set base tempo on second note
baseIntervalMs = intervalInMs;
print("(Base tempo = ${60 / intervalInMs * 1000})");
return true;
}
return baseIntervalMs * 0.75 < intervalInMs && intervalInMs < baseIntervalMs * 1.25;
}
}
class StartGameState extends GameState {
@override
String getPrompt() {
return 'Type ready to start the game';
}
@override
void process(String input, MysteryGame game) {
if (input == 'ready') {
game.state = TheKitchenGameState();
}
}
}
class SuccessGameState extends GameState {
@override
String getPrompt() {
return 'Congratulations! You are successful 🎉';
}
@override
void process(String input, MysteryGame game) {
if (input == 'RIP') {
game.state = DeadGameState();
}
}
}
class DeadGameState extends GameState {
@override
String getPrompt() {
return 'You are dead. Like this game? Feel free to retry.';
}
@override
void process(String input, MysteryGame game) {
if (input == 'retry') {
game.state = StartGameState();
}
}
}
//#endregion
class MysteryGame {
GameState state;
MysteryGame() {
state = StartGameState();
}
String getPrompt() {
return state.getPrompt();
}
void process(String input) {
return state.process(input, this);
}
}
void main() {
print('MysteryMaze v1.0');
print('---');
MysteryGame game = MysteryGame();
while (true) {
if (game.getPrompt() != null) {
print(game.getPrompt());
}
String input = stdin.readLineSync();
if (input == 'exit') {
break;
} else {
game.process(input);
}
}
print('Good bye! Come MysteryMaze again soon!');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment