From e1f7d0125402619809a8a0045fd75742a3745940 Mon Sep 17 00:00:00 2001 From: Paul Mathieu Date: Tue, 28 Feb 2023 16:55:35 -0800 Subject: [PATCH] Initial game. Couple of rooms, one object. --- Action.java | 3 + Item.java | 9 +++ Jeu.java | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Place.java | 12 +++ Player.java | 12 +++ 5 files changed, 243 insertions(+) create mode 100644 Action.java create mode 100644 Item.java create mode 100644 Jeu.java create mode 100644 Place.java create mode 100644 Player.java diff --git a/Action.java b/Action.java new file mode 100644 index 0000000..a0ef04a --- /dev/null +++ b/Action.java @@ -0,0 +1,3 @@ +public interface Action { + public boolean match(String input, Player player); +} \ No newline at end of file diff --git a/Item.java b/Item.java new file mode 100644 index 0000000..eec2a91 --- /dev/null +++ b/Item.java @@ -0,0 +1,9 @@ +public class Item { + public final String name; + public String description; + public Action action; + + public Item(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/Jeu.java b/Jeu.java new file mode 100644 index 0000000..6828a84 --- /dev/null +++ b/Jeu.java @@ -0,0 +1,207 @@ +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 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(); + } +} \ No newline at end of file diff --git a/Place.java b/Place.java new file mode 100644 index 0000000..48ef273 --- /dev/null +++ b/Place.java @@ -0,0 +1,12 @@ +import java.util.ArrayList; +import java.util.List; + +public class Place { + public final String name; + public String description; + public List actions = new ArrayList<>(); + + public Place(final String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/Player.java b/Player.java new file mode 100644 index 0000000..ee3eb0a --- /dev/null +++ b/Player.java @@ -0,0 +1,12 @@ +import java.util.ArrayList; +import java.util.List; + +public class Player { + public final String name; + public Place place; + public List items = new ArrayList<>(); + + public Player(final String name) { + this.name = name; + } +} \ No newline at end of file