javajeu/Jeu.java

207 lines
7.5 KiB
Java
Raw Normal View History

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Pattern;
import java.util.stream.Stream;
public class Jeu {
static interface ThenThat {
public void run(Player player);
}
static class ChainAction implements Action {
final Action ifthis;
ThenThat thenthat;
public ChainAction(Action ifthis) {
this.ifthis = ifthis;
}
public ChainAction then(ThenThat thenthat) {
this.thenthat = thenthat;
return new ChainAction(this);
}
@Override
public boolean match(String input, Player player) {
if (ifthis.match(input, player)) {
if (thenthat != null) {
thenthat.run(player);
}
return true;
}
return false;
}
}
static ThenThat say(String reaction) {
return p -> System.out.println(reaction);
}
static ChainAction getRegexpMatcher(String regexp) {
Pattern p = Pattern.compile(regexp);
return new ChainAction((input, player) -> {
return p.matcher(input).matches();
});
}
static ChainAction getVOMatcher(String verb, String object) {
return getRegexpMatcher(verb + "( the)? " + object);
}
static ChainAction getVOReaction(String verb, String object, String reaction) {
return getVOMatcher(verb, object).then(say(reaction));
}
static class StateMachineAction implements Action {
final Action matcher;
final Map<Integer, ThenThat> reactions = new HashMap<>();
public int state = 0;
public StateMachineAction(Action matcher) {
this.matcher = matcher;
}
public StateMachineAction when(int state, ThenThat thenthat) {
this.reactions.put(state, thenthat);
return this;
}
@Override
public boolean match(String input, Player player) {
if (!this.matcher.match(input, player)) {
return false;
}
if (this.reactions.containsKey(this.state)) {
this.reactions.get(this.state).run(player);
}
return true;
}
}
static class OnceAction extends StateMachineAction {
public OnceAction(Action matcher) {
super(matcher);
}
public OnceAction atFirst(ThenThat thenThat) {
this.when(0, player -> {
thenThat.run(player);
this.state = 1;
});
return this;
}
public OnceAction thenLater(ThenThat thenThat) {
this.when(1, thenThat);
return this;
}
}
static Place makeWorld() {
Place startingPoint = new Place("Some sort of place");
startingPoint.description = "You find yourself in MadVillain's lair.\n" +
"It's reaaally dark here. You can feel a light switch on the wall on your right.";
Place hallWay = new Place("Hallway");
hallWay.description = "This is the hallway that you came from. You don't spend much time looking at it\n" +
"so I won't spend much time describing it. It leads *outside*. Fresh air.";
Place outside = new Place("outside");
outside.description = "The great outdoors. I mean, it's still the city. Dull gray and mornful city.\n" +
"But it's also outdoors. And great, in a way. You can go anywhere. If you can.";
outside.actions.add(getVOReaction("go to", "hallway", "There's nothing to do there anymore."));
hallWay.actions.add(getRegexpMatcher("(go|get) (out|outside)").then(player -> {
System.out.println("The bright light of an overcast mid-morning in the city blinds you for a few seconds.\n" +
"It's not actually very bright. The smog absorbs a sizeable portion of the meager apricity.");
player.place = outside;
}));
final Action takeNotebook = new OnceAction(getVOMatcher("take", "notebook"))
.atFirst(player -> {
System.out.println("You reach out and take the notebook. It's not very clean.");
final Item notebook = new Item("notebook");
final Action read = new OnceAction(getVOMatcher("read", "notebook"))
.atFirst(say("It's full of gibberish and satanic doodles. You feel sullied."))
.thenLater(say("No way you open this book again."));
notebook.action = read;
player.items.add(notebook);
startingPoint.description = "An extremely banal room. There's nothing here.\n" +
"I mean there is NOTHING here.\n" +
"Except the door behind you. You know, the DOOR.";
}).thenLater(say("It's already in your pocket!"));
final Action openDoor = getVOMatcher("open", "door").then(player -> {
if (player.items.stream().anyMatch(i -> i.name.equals("notebook"))) {
System.out.println("Having spent enough time in this sordid place, you turn on your heels and head out.");
player.place = hallWay;
} else {
System.out.println("Ahem. I said there is a NOTEBOOK here.");
}
});
final Action flipSwitch = new OnceAction(
getRegexpMatcher("(turn ((the )?lights? on|on( the)? lights?)|flip( the)?( light)? switch)"))
.atFirst(player -> {
System.out.println("*clic*");
startingPoint.description = "An extremely banal room. There's nothing here.\n" +
"I mean, there's nothing here, aside from a weathered notebook.\n" +
"There's also a door, just behind you.";
startingPoint.actions.add(takeNotebook);
startingPoint.actions.add(openDoor);
})
.thenLater(say("It's an LED bulb, so it's ok to leave the light on."));
startingPoint.actions.add(flipSwitch);
return startingPoint;
}
static boolean match(Action[] actions, String input, Player player) {
for (final Action action : actions) {
if (action.match(input, player)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("What is your name?");
String name = scanner.nextLine();
Player player = new Player(name);
player.place = makeWorld();
System.out.println("Howdy there, Detective " + name+ ".");
System.out.println(player.place.description);
while (true) {
System.out.print("> ");
String line = scanner.nextLine();
if (line.startsWith("bye")) {
break;
}
final Action look = getRegexpMatcher("look( (here|around))?")
.then(p -> System.out.println(p.place.description));
Action[] actions = Stream.concat(
Stream.concat(
player.place.actions.stream(),
player.items.stream().map(i -> i.action)),
Arrays.stream(new Action[] { look })).toArray(Action[]::new);
if (!match(actions, line, player)) {
System.out.println("Wot?");
}
}
scanner.close();
}
}